mirror of
https://github.com/qdm12/ddns-updater.git
synced 2026-04-05 08:54:09 -04:00
fix(ipv6): add JSON IPv6 suffix parameter (#611)
- Remove `IPV6_PREFIX` environment variable (unneeded) and remove associated code - Update all documentation for each provider supporting IPv6 - Build IPv6 as prefix:suffix when getting it from a public IP source for each record IPv6 suffix parameter - Automatically disable provider_ip if public ip is IPv6 and IPv6 suffix is set (they are not compatible with each other)
This commit is contained in:
@@ -73,7 +73,6 @@ ENV \
|
|||||||
# Core
|
# Core
|
||||||
CONFIG= \
|
CONFIG= \
|
||||||
PERIOD=5m \
|
PERIOD=5m \
|
||||||
IPV6_PREFIX=/128 \
|
|
||||||
UPDATE_COOLDOWN_PERIOD=5m \
|
UPDATE_COOLDOWN_PERIOD=5m \
|
||||||
PUBLICIP_FETCHERS=all \
|
PUBLICIP_FETCHERS=all \
|
||||||
PUBLICIP_HTTP_PROVIDERS=all \
|
PUBLICIP_HTTP_PROVIDERS=all \
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ The program reads the configuration from a JSON object, either from a file or fr
|
|||||||
docker run -d -p 8000:8000/tcp -v "$(pwd)"/data:/updater/data qmcgaw/ddns-updater
|
docker run -d -p 8000:8000/tcp -v "$(pwd)"/data:/updater/data qmcgaw/ddns-updater
|
||||||
```
|
```
|
||||||
|
|
||||||
1. ⚠️ If you use IPv6, you might need to set `-e IPV6_PREFIX=/64` (`/64` is your prefix, depending on your ISP)
|
|
||||||
1. (Optional) You can also set your JSON configuration as a single environment variable line (i.e. `{"settings": [{"provider": "namecheap", ...}]}`), which takes precedence over config.json. Note however that if you don't bind mount the `/updater/data` directory, there won't be a persistent database file `/updater/updates.json` but it will still work.
|
1. (Optional) You can also set your JSON configuration as a single environment variable line (i.e. `{"settings": [{"provider": "namecheap", ...}]}`), which takes precedence over config.json. Note however that if you don't bind mount the `/updater/data` directory, there won't be a persistent database file `/updater/updates.json` but it will still work.
|
||||||
|
|
||||||
### Next steps
|
### Next steps
|
||||||
@@ -224,7 +223,6 @@ Note that:
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `CONFIG` | | One line JSON object containing the entire config (takes precedence over config.json file) if specified |
|
| `CONFIG` | | One line JSON object containing the entire config (takes precedence over config.json file) if specified |
|
||||||
| `PERIOD` | `5m` | Default period of IP address check, following [this format](https://golang.org/pkg/time/#ParseDuration) |
|
| `PERIOD` | `5m` | Default period of IP address check, following [this format](https://golang.org/pkg/time/#ParseDuration) |
|
||||||
| `IPV6_PREFIX` | `/128` | IPv6 prefix used to mask your public IPv6 address and your record IPv6 address. Ranges from `/0` to `/128` depending on your ISP. |
|
|
||||||
| `PUBLICIP_FETCHERS` | `all` | Comma separated fetcher types to obtain the public IP address from `http` and `dns` |
|
| `PUBLICIP_FETCHERS` | `all` | Comma separated fetcher types to obtain the public IP address from `http` and `dns` |
|
||||||
| `PUBLICIP_HTTP_PROVIDERS` | `all` | Comma separated providers to obtain the public IP address (ipv4 or ipv6). See the [Public IP section](#public-ip) |
|
| `PUBLICIP_HTTP_PROVIDERS` | `all` | Comma separated providers to obtain the public IP address (ipv4 or ipv6). See the [Public IP section](#public-ip) |
|
||||||
| `PUBLICIPV4_HTTP_PROVIDERS` | `all` | Comma separated providers to obtain the public IPv4 address only. See the [Public IP section](#public-ip) |
|
| `PUBLICIPV4_HTTP_PROVIDERS` | `all` | Comma separated providers to obtain the public IPv4 address only. See the [Public IP section](#public-ip) |
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
_ "time/tzdata"
|
_ "time/tzdata"
|
||||||
@@ -248,8 +247,7 @@ func _main(ctx context.Context, reader *reader.Reader, args []string, logger log
|
|||||||
|
|
||||||
updater := update.NewUpdater(db, client, shoutrrrClient, logger)
|
updater := update.NewUpdater(db, client, shoutrrrClient, logger)
|
||||||
runner := update.NewRunner(db, updater, ipGetter, config.Update.Period,
|
runner := update.NewRunner(db, updater, ipGetter, config.Update.Period,
|
||||||
ipv6PrefixToBits(config.IPv6.Prefix), config.Update.Cooldown, logger,
|
config.Update.Cooldown, logger, resolver, timeNow, hioClient)
|
||||||
resolver, timeNow, hioClient)
|
|
||||||
|
|
||||||
runnerHandler, runnerCtx, runnerDone := goshutdown.NewGoRoutineHandler("runner")
|
runnerHandler, runnerCtx, runnerDone := goshutdown.NewGoRoutineHandler("runner")
|
||||||
go runner.Run(runnerCtx, runnerDone)
|
go runner.Run(runnerCtx, runnerDone)
|
||||||
@@ -326,12 +324,3 @@ func backupRunLoop(ctx context.Context, done chan<- struct{}, backupPeriod time.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ipv6PrefixToBits(prefix string) (maskBits uint8) {
|
|
||||||
prefix = strings.TrimPrefix(prefix, "/")
|
|
||||||
n, err := strconv.Atoi(prefix)
|
|
||||||
if err != nil {
|
|
||||||
panic(err) // prefix already validated before
|
|
||||||
}
|
|
||||||
return uint8(n)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"access_key_id": "your access_key_id",
|
"access_key_id": "your access_key_id",
|
||||||
"access_secret": "your access_secret",
|
"access_secret": "your access_secret",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -29,5 +30,6 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "host",
|
"host": "host",
|
||||||
"username": "dynXXXXXXX",
|
"username": "dynXXXXXXX",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -29,5 +30,6 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"ttl": 600,
|
"ttl": 600,
|
||||||
"token": "yourtoken",
|
"token": "yourtoken",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -36,5 +37,6 @@ See [this issue comment for context](https://github.com/qdm12/ddns-updater/issue
|
|||||||
|
|
||||||
- `"proxied"` can be set to `true` to use the proxy services of Cloudflare
|
- `"proxied"` can be set to `true` to use the proxy services of Cloudflare
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
Special thanks to @Starttoaster for helping out with the [documentation](https://gist.github.com/Starttoaster/07d568c2a99ad7631dd776688c988326) and testing.
|
Special thanks to @Starttoaster for helping out with the [documentation](https://gist.github.com/Starttoaster/07d568c2a99ad7631dd776688c988326) and testing.
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ Feel free to open issues to extend its configuration options.
|
|||||||
"ipv4key": "ipv4",
|
"ipv4key": "ipv4",
|
||||||
"ipv6key": "ipv6",
|
"ipv6key": "ipv6",
|
||||||
"success_regex": "good",
|
"success_regex": "good",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -38,3 +39,4 @@ Feel free to open issues to extend its configuration options.
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "@",
|
"host": "@",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,3 +28,4 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
"username": "user",
|
"username": "user",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"dual_stack": false,
|
"dual_stack": false,
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -34,5 +35,6 @@
|
|||||||
- if it is `false`, the updates are done using the `ip` parameter and only one IP address can be set (ipv4 or ipv6, whichever is last sent).
|
- if it is `false`, the updates are done using the `ip` parameter and only one IP address can be set (ipv4 or ipv6, whichever is last sent).
|
||||||
- if it is `true`, the updates are done using the `ip` and `ip6` parameters, for IPv4 and IPv6 respectively, and both can be set on the same record
|
- if it is `true`, the updates are done using the `ip` and `ip6` parameters, for IPv4 and IPv6 respectively, and both can be set on the same record
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"host": "host",
|
"host": "host",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": false
|
"provider_ip": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "@",
|
"host": "@",
|
||||||
"token": "yourtoken",
|
"token": "yourtoken",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,5 +28,6 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"provider_ip": true,
|
"provider_ip": true,
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -31,5 +32,6 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "@",
|
"host": "@",
|
||||||
"token": "yourtoken",
|
"token": "yourtoken",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,5 +28,6 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
"name": "something",
|
"name": "something",
|
||||||
"username": "username",
|
"username": "username",
|
||||||
"key": "key",
|
"key": "key",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "@",
|
"host": "@",
|
||||||
"key": "key",
|
"key": "key",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,5 +28,6 @@
|
|||||||
|
|
||||||
- `"host"` is your host and can be a subdomain or `"@"`. It defaults to `"@"`.
|
- `"host"` is your host and can be a subdomain or `"@"`. It defaults to `"@"`.
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"host": "host",
|
"host": "host",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (**NOT** your IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (**NOT** your IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"username": "username",
|
"username": "username",
|
||||||
"client_key": "client_key",
|
"client_key": "client_key",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -29,5 +30,6 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
- `"group"` specify the Group for which you want to set the IP (will update any domains and subdomains in the same group)
|
- `"group"` specify the Group for which you want to set the IP (will update any domains and subdomains in the same group)
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "host",
|
"host": "host",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ This provider uses Gandi v5 API
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"personal_access_token": "token",
|
"personal_access_token": "token",
|
||||||
"ttl": 3600,
|
"ttl": 3600,
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -30,6 +31,7 @@ This provider uses Gandi v5 API
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"ttl"` default is `3600`
|
- `"ttl"` default is `3600`
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
},
|
},
|
||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "@",
|
"host": "@",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -35,3 +36,4 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"key": "key",
|
"key": "key",
|
||||||
"secret": "secret",
|
"secret": "secret",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"provider_ip": true,
|
"provider_ip": true,
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"ttl": 600,
|
"ttl": 600,
|
||||||
"token": "yourtoken",
|
"token": "yourtoken",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -32,3 +33,4 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -29,5 +30,6 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "@",
|
"host": "@",
|
||||||
"api_key": "api_key",
|
"api_key": "api_key",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,3 +28,4 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"host": "@",
|
"host": "@",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"email": "email",
|
"email": "email",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ttl": 300,
|
"ttl": 300,
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -33,3 +34,4 @@
|
|||||||
|
|
||||||
- `"ttl"` is the time this record can be cached for in seconds. Name.com allows a minimum TTL of 300, or 5 minutes. Name.com defaults to 300 if not provided.
|
- `"ttl"` is the time this record can be cached for in seconds. Name.com allows a minimum TTL of 300, or 5 minutes. Name.com defaults to 300 if not provided.
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ Also keep in mind, that TTL, Expire, Retry and Refresh values of the given Domai
|
|||||||
"api_key": "xxxxx",
|
"api_key": "xxxxx",
|
||||||
"password": "yyyyy",
|
"password": "yyyyy",
|
||||||
"customer_number": "111111",
|
"customer_number": "111111",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -35,3 +36,4 @@ Also keep in mind, that TTL, Expire, Retry and Refresh values of the given Domai
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"key": "key",
|
"key": "key",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"domain": "domain.com",
|
"domain": "domain.com",
|
||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -27,3 +28,4 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -42,6 +43,7 @@ The ZoneDNS implementation allows you to update any record name including *.your
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
- `"mode"` select between two modes, OVH's dynamic hosting service (`"dynamic"`) or OVH's API (`"api"`). Default is `"dynamic"`
|
- `"mode"` select between two modes, OVH's dynamic hosting service (`"dynamic"`) or OVH's API (`"api"`). Default is `"dynamic"`
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"api_key": "sk1_7d119e3f656b00ae042980302e1425a04163c476efec1833q3cb0w54fc6f5022",
|
"api_key": "sk1_7d119e3f656b00ae042980302e1425a04163c476efec1833q3cb0w54fc6f5022",
|
||||||
"secret_api_key": "pk1_5299b57125c8f3cdf347d2fe0e713311ee3a1e11f11a14942b26472593e35368",
|
"secret_api_key": "pk1_5299b57125c8f3cdf347d2fe0e713311ee3a1e11f11a14942b26472593e35368",
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"provider_ip": true,
|
"provider_ip": true,
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
"password": "servercow_password",
|
"password": "servercow_password",
|
||||||
"ttl": 600,
|
"ttl": 600,
|
||||||
"provider_ip": true,
|
"provider_ip": true,
|
||||||
"ip_version": "ipv4"
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
|
|
||||||
- `"ttl"` can be set to an integer value for record TTL in seconds (if not set the default is 120)
|
- `"ttl"` can be set to an integer value for record TTL in seconds (if not set the default is 120)
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"password": "password",
|
"password": "password",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -38,4 +39,5 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (**not IPv6**)automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (**not IPv6**)automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"host": "@",
|
"host": "@",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"email": "email@domain.com",
|
"email": "email@domain.com",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ set the environment variable as `PERIOD=11m` to check your public IP address and
|
|||||||
"username": "username",
|
"username": "username",
|
||||||
"token": "token",
|
"token": "token",
|
||||||
"ip_version": "ipv4",
|
"ip_version": "ipv4",
|
||||||
|
"ipv6_suffix": "",
|
||||||
"provider_ip": true
|
"provider_ip": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -36,6 +37,7 @@ set the environment variable as `PERIOD=11m` to check your public IP address and
|
|||||||
### Optional parameters
|
### Optional parameters
|
||||||
|
|
||||||
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
- `"ip_version"` can be `ipv4` (A records), or `ipv6` (AAAA records) or `ipv4 or ipv6` (update one of the two, depending on the public ip found). It defaults to `ipv4 or ipv6`.
|
||||||
|
- `"ipv6_suffix"` is the IPv6 interface indentifier suffix to use. It can be for example `0:0:0:0:72ad:8fbb:a54e:bedd/64`. If left empty, it defaults to no suffix and the raw public IPv6 address obtained is used in the record updating.
|
||||||
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
- `"provider_ip"` can be set to `true` to let your DNS provider determine your IPv4 address (and/or IPv6 address) automatically when you send an update request, without sending the new IP address detected by the program in the request.
|
||||||
|
|
||||||
## Domain setup
|
## Domain setup
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/qdm12/gosettings"
|
|
||||||
"github.com/qdm12/gosettings/reader"
|
|
||||||
"github.com/qdm12/gotree"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IPv6 struct {
|
|
||||||
// Prefix is the IPv6 mask, for example /128
|
|
||||||
Prefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IPv6) setDefaults() {
|
|
||||||
i.Prefix = gosettings.DefaultComparable(i.Prefix, "/128")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i IPv6) Validate() (err error) {
|
|
||||||
err = validateIPv6Prefix(i.Prefix)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrIPv6PrefixFormat = errors.New("IPv6 prefix format is incorrect")
|
|
||||||
)
|
|
||||||
|
|
||||||
func validateIPv6Prefix(prefix string) (err error) {
|
|
||||||
prefix = strings.TrimPrefix(prefix, "/")
|
|
||||||
|
|
||||||
const base, bits = 10, 8
|
|
||||||
_, err = strconv.ParseUint(prefix, base, bits)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("%w: cannot parse %q as uint8", ErrIPv6PrefixFormat, prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxBits = 128
|
|
||||||
if bits > maxBits {
|
|
||||||
return fmt.Errorf("%w: %d bits cannot be larger than %d",
|
|
||||||
ErrIPv6PrefixFormat, bits, maxBits)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i IPv6) String() string {
|
|
||||||
return i.toLinesNode().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i IPv6) toLinesNode() *gotree.Node {
|
|
||||||
node := gotree.New("IPv6")
|
|
||||||
node.Appendf("Prefix: %s", i.Prefix)
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IPv6) read(reader *reader.Reader) {
|
|
||||||
i.Prefix = reader.String("IPV6_PREFIX")
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_validateIPv6Prefix(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
testCases := map[string]struct {
|
|
||||||
prefixDecimal string
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
"empty": {
|
|
||||||
err: fmt.Errorf(`IPv6 prefix format is incorrect: ` +
|
|
||||||
`cannot parse "" as uint8`),
|
|
||||||
},
|
|
||||||
"malformed": {
|
|
||||||
prefixDecimal: "malformed",
|
|
||||||
err: fmt.Errorf(`IPv6 prefix format is incorrect: ` +
|
|
||||||
`cannot parse "malformed" as uint8`),
|
|
||||||
},
|
|
||||||
"with leading slash": {
|
|
||||||
prefixDecimal: "/78",
|
|
||||||
},
|
|
||||||
"without leading slash": {
|
|
||||||
prefixDecimal: "78",
|
|
||||||
},
|
|
||||||
"full IPv6 mask": {
|
|
||||||
prefixDecimal: "/128",
|
|
||||||
},
|
|
||||||
"zero IPv6 mask": {
|
|
||||||
prefixDecimal: "/0",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, testCase := range testCases {
|
|
||||||
testCase := testCase
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
err := validateIPv6Prefix(testCase.prefixDecimal)
|
|
||||||
|
|
||||||
if testCase.err != nil {
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Equal(t, testCase.err.Error(), err.Error())
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,6 @@ type Config struct {
|
|||||||
Update Update
|
Update Update
|
||||||
PubIP PubIP
|
PubIP PubIP
|
||||||
Resolver Resolver
|
Resolver Resolver
|
||||||
IPv6 IPv6
|
|
||||||
Server Server
|
Server Server
|
||||||
Health Health
|
Health Health
|
||||||
Paths Paths
|
Paths Paths
|
||||||
@@ -26,7 +25,6 @@ func (c *Config) SetDefaults() {
|
|||||||
c.Update.setDefaults()
|
c.Update.setDefaults()
|
||||||
c.PubIP.setDefaults()
|
c.PubIP.setDefaults()
|
||||||
c.Resolver.setDefaults()
|
c.Resolver.setDefaults()
|
||||||
c.IPv6.setDefaults()
|
|
||||||
c.Server.setDefaults()
|
c.Server.setDefaults()
|
||||||
c.Health.SetDefaults()
|
c.Health.SetDefaults()
|
||||||
c.Paths.setDefaults()
|
c.Paths.setDefaults()
|
||||||
@@ -44,7 +42,6 @@ func (c Config) Validate() (err error) {
|
|||||||
"update": &c.Update,
|
"update": &c.Update,
|
||||||
"public ip": &c.PubIP,
|
"public ip": &c.PubIP,
|
||||||
"resolver": &c.Resolver,
|
"resolver": &c.Resolver,
|
||||||
"ipv6": &c.IPv6,
|
|
||||||
"server": &c.Server,
|
"server": &c.Server,
|
||||||
"health": &c.Health,
|
"health": &c.Health,
|
||||||
"paths": &c.Paths,
|
"paths": &c.Paths,
|
||||||
@@ -73,7 +70,6 @@ func (c Config) toLinesNode() *gotree.Node {
|
|||||||
node.AppendNode(c.Update.toLinesNode())
|
node.AppendNode(c.Update.toLinesNode())
|
||||||
node.AppendNode(c.PubIP.toLinesNode())
|
node.AppendNode(c.PubIP.toLinesNode())
|
||||||
node.AppendNode(c.Resolver.ToLinesNode())
|
node.AppendNode(c.Resolver.ToLinesNode())
|
||||||
node.AppendNode(c.IPv6.toLinesNode())
|
|
||||||
node.AppendNode(c.Server.toLinesNode())
|
node.AppendNode(c.Server.toLinesNode())
|
||||||
node.AppendNode(c.Health.toLinesNode())
|
node.AppendNode(c.Health.toLinesNode())
|
||||||
node.AppendNode(c.Paths.toLinesNode())
|
node.AppendNode(c.Paths.toLinesNode())
|
||||||
@@ -105,8 +101,6 @@ func (c *Config) Read(reader *reader.Reader,
|
|||||||
return fmt.Errorf("reading resolver settings: %w", err)
|
return fmt.Errorf("reading resolver settings: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.IPv6.read(reader)
|
|
||||||
|
|
||||||
err = c.Server.read(reader, warner)
|
err = c.Server.read(reader, warner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading server settings: %w", err)
|
return fmt.Errorf("reading server settings: %w", err)
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ func Test_Settings_String(t *testing.T) {
|
|||||||
| └── DNS over TLS providers
|
| └── DNS over TLS providers
|
||||||
| └── all
|
| └── all
|
||||||
├── Resolver: use Go default resolver
|
├── Resolver: use Go default resolver
|
||||||
├── IPv6
|
|
||||||
| └── Prefix: /128
|
|
||||||
├── Server
|
├── Server
|
||||||
| ├── Listening address: :8000
|
| ├── Listening address: :8000
|
||||||
| └── Root URL: /
|
| └── Root URL: /
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -16,10 +17,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type commonSettings struct {
|
type commonSettings struct {
|
||||||
Provider string `json:"provider"`
|
Provider string `json:"provider"`
|
||||||
Domain string `json:"domain"`
|
Domain string `json:"domain"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
IPVersion string `json:"ip_version"`
|
IPVersion string `json:"ip_version"`
|
||||||
|
IPv6Suffix netip.Prefix `json:"ipv6_suffix,omitempty"`
|
||||||
// Retro values for warnings
|
// Retro values for warnings
|
||||||
IPMethod *string `json:"ip_method,omitempty"`
|
IPMethod *string `json:"ip_method,omitempty"`
|
||||||
Delay *uint64 `json:"delay,omitempty"`
|
Delay *uint64 `json:"delay,omitempty"`
|
||||||
@@ -165,10 +167,16 @@ func makeSettingsFromObject(common commonSettings, rawSettings json.RawMessage)
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ipVersion != ipversion.IP6 && common.IPv6Suffix.IsValid() {
|
||||||
|
warnings = append(warnings,
|
||||||
|
fmt.Sprintf("IPv6 suffix specified as %s but IP version is %s",
|
||||||
|
common.IPv6Suffix, ipVersion))
|
||||||
|
}
|
||||||
|
|
||||||
providers = make([]provider.Provider, len(hosts))
|
providers = make([]provider.Provider, len(hosts))
|
||||||
for i, host := range hosts {
|
for i, host := range hosts {
|
||||||
providers[i], err = provider.New(providerName, rawSettings, common.Domain,
|
providers[i], err = provider.New(providerName, rawSettings, common.Domain,
|
||||||
host, ipVersion)
|
host, ipVersion, common.IPv6Suffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, warnings, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ type Provider interface {
|
|||||||
HTML() models.HTMLRow
|
HTML() models.HTMLRow
|
||||||
Proxied() bool
|
Proxied() bool
|
||||||
IPVersion() ipversion.IPVersion
|
IPVersion() ipversion.IPVersion
|
||||||
|
IPv6Suffix() netip.Prefix
|
||||||
Update(ctx context.Context, client *http.Client, ip netip.Addr) (newIP netip.Addr, err error)
|
Update(ctx context.Context, client *http.Client, ip netip.Addr) (newIP netip.Addr, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,94 +72,94 @@ var ErrProviderUnknown = errors.New("unknown provider")
|
|||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func New(providerName models.Provider, data json.RawMessage, domain, host string, //nolint:ireturn
|
func New(providerName models.Provider, data json.RawMessage, domain, host string, //nolint:ireturn
|
||||||
ipVersion ipversion.IPVersion) (provider Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (provider Provider, err error) {
|
||||||
switch providerName {
|
switch providerName {
|
||||||
case constants.Aliyun:
|
case constants.Aliyun:
|
||||||
return aliyun.New(data, domain, host, ipVersion)
|
return aliyun.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.AllInkl:
|
case constants.AllInkl:
|
||||||
return allinkl.New(data, domain, host, ipVersion)
|
return allinkl.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Cloudflare:
|
case constants.Cloudflare:
|
||||||
return cloudflare.New(data, domain, host, ipVersion)
|
return cloudflare.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Custom:
|
case constants.Custom:
|
||||||
return custom.New(data, domain, host, ipVersion)
|
return custom.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Dd24:
|
case constants.Dd24:
|
||||||
return dd24.New(data, domain, host, ipVersion)
|
return dd24.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DdnssDe:
|
case constants.DdnssDe:
|
||||||
return ddnss.New(data, domain, host, ipVersion)
|
return ddnss.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DeSEC:
|
case constants.DeSEC:
|
||||||
return desec.New(data, domain, host, ipVersion)
|
return desec.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DigitalOcean:
|
case constants.DigitalOcean:
|
||||||
return digitalocean.New(data, domain, host, ipVersion)
|
return digitalocean.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DNSOMatic:
|
case constants.DNSOMatic:
|
||||||
return dnsomatic.New(data, domain, host, ipVersion)
|
return dnsomatic.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DNSPod:
|
case constants.DNSPod:
|
||||||
return dnspod.New(data, domain, host, ipVersion)
|
return dnspod.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DonDominio:
|
case constants.DonDominio:
|
||||||
return dondominio.New(data, domain, host, ipVersion)
|
return dondominio.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Dreamhost:
|
case constants.Dreamhost:
|
||||||
return dreamhost.New(data, domain, host, ipVersion)
|
return dreamhost.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DuckDNS:
|
case constants.DuckDNS:
|
||||||
return duckdns.New(data, domain, host, ipVersion)
|
return duckdns.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Dyn:
|
case constants.Dyn:
|
||||||
return dyn.New(data, domain, host, ipVersion)
|
return dyn.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Dynu:
|
case constants.Dynu:
|
||||||
return dynu.New(data, domain, host, ipVersion)
|
return dynu.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.DynV6:
|
case constants.DynV6:
|
||||||
return dynv6.New(data, domain, host, ipVersion)
|
return dynv6.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.EasyDNS:
|
case constants.EasyDNS:
|
||||||
return easydns.New(data, domain, host, ipVersion)
|
return easydns.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.FreeDNS:
|
case constants.FreeDNS:
|
||||||
return freedns.New(data, domain, host, ipVersion)
|
return freedns.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Gandi:
|
case constants.Gandi:
|
||||||
return gandi.New(data, domain, host, ipVersion)
|
return gandi.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.GCP:
|
case constants.GCP:
|
||||||
return gcp.New(data, domain, host, ipVersion)
|
return gcp.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.GoDaddy:
|
case constants.GoDaddy:
|
||||||
return godaddy.New(data, domain, host, ipVersion)
|
return godaddy.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.HE:
|
case constants.HE:
|
||||||
return he.New(data, domain, host, ipVersion)
|
return he.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Hetzner:
|
case constants.Hetzner:
|
||||||
return hetzner.New(data, domain, host, ipVersion)
|
return hetzner.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Infomaniak:
|
case constants.Infomaniak:
|
||||||
return infomaniak.New(data, domain, host, ipVersion)
|
return infomaniak.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.INWX:
|
case constants.INWX:
|
||||||
return inwx.New(data, domain, host, ipVersion)
|
return inwx.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Ionos:
|
case constants.Ionos:
|
||||||
return ionos.New(data, domain, host, ipVersion)
|
return ionos.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Linode:
|
case constants.Linode:
|
||||||
return linode.New(data, domain, host, ipVersion)
|
return linode.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.LuaDNS:
|
case constants.LuaDNS:
|
||||||
return luadns.New(data, domain, host, ipVersion)
|
return luadns.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Namecheap:
|
case constants.Namecheap:
|
||||||
return namecheap.New(data, domain, host)
|
return namecheap.New(data, domain, host)
|
||||||
case constants.NameCom:
|
case constants.NameCom:
|
||||||
return namecom.New(data, domain, host, ipVersion)
|
return namecom.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Netcup:
|
case constants.Netcup:
|
||||||
return netcup.New(data, domain, host, ipVersion)
|
return netcup.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Njalla:
|
case constants.Njalla:
|
||||||
return njalla.New(data, domain, host, ipVersion)
|
return njalla.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.NoIP:
|
case constants.NoIP:
|
||||||
return noip.New(data, domain, host, ipVersion)
|
return noip.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.NowDNS:
|
case constants.NowDNS:
|
||||||
return nowdns.New(data, domain, ipVersion)
|
return nowdns.New(data, domain, ipVersion, ipv6Suffix)
|
||||||
case constants.OpenDNS:
|
case constants.OpenDNS:
|
||||||
return opendns.New(data, domain, host, ipVersion)
|
return opendns.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.OVH:
|
case constants.OVH:
|
||||||
return ovh.New(data, domain, host, ipVersion)
|
return ovh.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Porkbun:
|
case constants.Porkbun:
|
||||||
return porkbun.New(data, domain, host, ipVersion)
|
return porkbun.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.SelfhostDe:
|
case constants.SelfhostDe:
|
||||||
return selfhostde.New(data, domain, host, ipVersion)
|
return selfhostde.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Servercow:
|
case constants.Servercow:
|
||||||
return servercow.New(data, domain, host, ipVersion)
|
return servercow.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Spdyn:
|
case constants.Spdyn:
|
||||||
return spdyn.New(data, domain, host, ipVersion)
|
return spdyn.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Strato:
|
case constants.Strato:
|
||||||
return strato.New(data, domain, host, ipVersion)
|
return strato.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Variomedia:
|
case constants.Variomedia:
|
||||||
return variomedia.New(data, domain, host, ipVersion)
|
return variomedia.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
case constants.Zoneedit:
|
case constants.Zoneedit:
|
||||||
return zoneedit.New(data, domain, host, ipVersion)
|
return zoneedit.New(data, domain, host, ipVersion, ipv6Suffix)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%w: %s", ErrProviderUnknown, providerName)
|
return nil, fmt.Errorf("%w: %s", ErrProviderUnknown, providerName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
accessKeyID string
|
accessKeyID string
|
||||||
accessSecret string
|
accessSecret string
|
||||||
region string
|
region string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
AccessKeyID string `json:"access_key_id"`
|
AccessKeyID string `json:"access_key_id"`
|
||||||
AccessSecret string `json:"access_secret"`
|
AccessSecret string `json:"access_secret"`
|
||||||
@@ -39,6 +41,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
accessKeyID: extraSettings.AccessKeyID,
|
accessKeyID: extraSettings.AccessKeyID,
|
||||||
accessSecret: extraSettings.AccessSecret,
|
accessSecret: extraSettings.AccessSecret,
|
||||||
region: "cn-hangzhou",
|
region: "cn-hangzhou",
|
||||||
@@ -79,6 +82,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -43,6 +45,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -82,6 +85,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -108,8 +115,9 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("host", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("host", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
if ip.Is6() { // ipv6
|
if !useProviderIP {
|
||||||
|
if ip.Is6() {
|
||||||
values.Set("myip6", ip.String())
|
values.Set("myip6", ip.String())
|
||||||
} else {
|
} else {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
@@ -171,7 +179,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
|
|
||||||
newIP = ips[0]
|
newIP = ips[0]
|
||||||
if !p.useProviderIP && ip.Compare(newIP) != 0 {
|
if !useProviderIP && ip.Compare(newIP) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
key string
|
key string
|
||||||
token string
|
token string
|
||||||
email string
|
email string
|
||||||
@@ -34,7 +35,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
@@ -52,6 +54,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
key: extraSettings.Key,
|
key: extraSettings.Key,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
email: extraSettings.Email,
|
email: extraSettings.Email,
|
||||||
@@ -116,6 +119,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return p.proxied
|
return p.proxied
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
url *url.URL
|
url *url.URL
|
||||||
ipv4Key string
|
ipv4Key string
|
||||||
ipv6Key string
|
ipv6Key string
|
||||||
@@ -29,7 +30,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
IPv4Key string `json:"ipv4key"`
|
IPv4Key string `json:"ipv4key"`
|
||||||
@@ -50,6 +52,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
url: parsedURL,
|
url: parsedURL,
|
||||||
ipv4Key: extraSettings.IPv4Key,
|
ipv4Key: extraSettings.IPv4Key,
|
||||||
ipv6Key: extraSettings.IPv6Key,
|
ipv6Key: extraSettings.IPv6Key,
|
||||||
@@ -95,6 +98,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,13 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
p *Provider, err error) {
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -41,6 +42,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
}
|
}
|
||||||
@@ -74,6 +76,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -101,7 +107,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", p.BuildDomainName())
|
values.Set("hostname", p.BuildDomainName())
|
||||||
values.Set("password", p.password)
|
values.Set("password", p.password)
|
||||||
if p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if useProviderIP {
|
||||||
values.Set("ip", "auto")
|
values.Set("ip", "auto")
|
||||||
} else {
|
} else {
|
||||||
values.Set("ip", ip.String())
|
values.Set("ip", ip.String())
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
dualStack bool
|
dualStack bool
|
||||||
@@ -29,7 +30,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -44,6 +46,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
dualStack: extraSettings.DualStack,
|
dualStack: extraSettings.DualStack,
|
||||||
@@ -84,6 +87,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -111,7 +118,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
values.Set("user", p.username)
|
values.Set("user", p.username)
|
||||||
values.Set("pwd", p.password)
|
values.Set("pwd", p.password)
|
||||||
values.Set("host", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("host", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
ipKey := "ip"
|
ipKey := "ip"
|
||||||
if p.dualStack && ip.Is6() { // ipv6 update for dual stack
|
if p.dualStack && ip.Is6() { // ipv6 update for dual stack
|
||||||
ipKey = "ip6"
|
ipKey = "ip6"
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
token string
|
token string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
UseProviderIP bool `json:"provider_ip"`
|
UseProviderIP bool `json:"provider_ip"`
|
||||||
@@ -43,6 +45,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
}
|
}
|
||||||
@@ -76,6 +79,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -102,7 +109,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
|
|||||||
@@ -18,14 +18,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
token string
|
ipv6Suffix netip.Prefix
|
||||||
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}{}
|
}{}
|
||||||
@@ -34,10 +36,11 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
token: extraSettings.Token,
|
ipv6Suffix: ipv6Suffix,
|
||||||
|
token: extraSettings.Token,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -69,6 +72,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -43,6 +45,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -80,6 +83,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return p.host == "all"
|
return p.host == "all"
|
||||||
}
|
}
|
||||||
@@ -106,7 +113,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
User: url.UserPassword(p.username, p.password),
|
User: url.UserPassword(p.username, p.password),
|
||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
values.Set("wildcard", "NOCHG")
|
values.Set("wildcard", "NOCHG")
|
||||||
@@ -172,7 +180,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
|
|
||||||
newIP = ips[0]
|
newIP = ips[0]
|
||||||
if !p.useProviderIP && ip.Compare(newIP) != 0 {
|
if !useProviderIP && ip.Compare(newIP) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
token string
|
ipv6Suffix netip.Prefix
|
||||||
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}{}
|
}{}
|
||||||
@@ -35,10 +37,11 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
token: extraSettings.Token,
|
ipv6Suffix: ipv6Suffix,
|
||||||
|
token: extraSettings.Token,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -70,6 +73,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
username string
|
ipv6Suffix netip.Prefix
|
||||||
key string
|
username string
|
||||||
name string
|
key string
|
||||||
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"` // retro-compatibility
|
Password string `json:"password"` // retro-compatibility
|
||||||
@@ -46,12 +48,13 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
username: extraSettings.Username,
|
ipv6Suffix: ipv6Suffix,
|
||||||
key: extraSettings.Key,
|
username: extraSettings.Username,
|
||||||
name: extraSettings.Name,
|
key: extraSettings.Key,
|
||||||
|
name: extraSettings.Name,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,6 +91,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
key string
|
ipv6Suffix netip.Prefix
|
||||||
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
}{}
|
}{}
|
||||||
@@ -38,10 +40,11 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
host = "@" // default
|
host = "@" // default
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
key: extraSettings.Key,
|
ipv6Suffix: ipv6Suffix,
|
||||||
|
key: extraSettings.Key,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -76,6 +79,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ import (
|
|||||||
type Provider struct {
|
type Provider struct {
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
token string
|
token string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, _, host string,
|
func New(data json.RawMessage, _, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
UseProviderIP bool `json:"provider_ip"`
|
UseProviderIP bool `json:"provider_ip"`
|
||||||
@@ -39,6 +41,7 @@ func New(data json.RawMessage, _, host string,
|
|||||||
p = &Provider{
|
p = &Provider{
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
}
|
}
|
||||||
@@ -52,12 +55,11 @@ func New(data json.RawMessage, _, host string,
|
|||||||
var tokenRegex = regexp.MustCompile(`^[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}$`)
|
var tokenRegex = regexp.MustCompile(`^[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}$`)
|
||||||
|
|
||||||
func (p *Provider) isValid() error {
|
func (p *Provider) isValid() error {
|
||||||
if !tokenRegex.MatchString(p.token) {
|
switch {
|
||||||
|
case !tokenRegex.MatchString(p.token):
|
||||||
return fmt.Errorf("%w: token %q does not match regex %q",
|
return fmt.Errorf("%w: token %q does not match regex %q",
|
||||||
errors.ErrTokenNotValid, p.token, tokenRegex)
|
errors.ErrTokenNotValid, p.token, tokenRegex)
|
||||||
}
|
case p.host == "@", p.host == "*":
|
||||||
switch p.host {
|
|
||||||
case "@", "*":
|
|
||||||
return fmt.Errorf("%w: %q is not valid",
|
return fmt.Errorf("%w: %q is not valid",
|
||||||
errors.ErrHostOnlySubdomain, p.host)
|
errors.ErrHostOnlySubdomain, p.host)
|
||||||
}
|
}
|
||||||
@@ -80,6 +82,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -107,7 +113,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
values.Set("verbose", "true")
|
values.Set("verbose", "true")
|
||||||
values.Set("domains", p.host)
|
values.Set("domains", p.host)
|
||||||
values.Set("token", p.token)
|
values.Set("token", p.token)
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
if ip.Is6() {
|
if ip.Is6() {
|
||||||
values.Set("ipv6", ip.String())
|
values.Set("ipv6", ip.String())
|
||||||
} else {
|
} else {
|
||||||
@@ -156,7 +163,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrReceivedNoIP)
|
return netip.Addr{}, fmt.Errorf("%w", errors.ErrReceivedNoIP)
|
||||||
}
|
}
|
||||||
newIP = ips[0]
|
newIP = ips[0]
|
||||||
if !p.useProviderIP && newIP.Compare(ip) != 0 {
|
if !useProviderIP && newIP.Compare(ip) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
username string
|
ipv6Suffix netip.Prefix
|
||||||
clientKey string
|
username string
|
||||||
|
clientKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"` // Retro-compatibility
|
Password string `json:"password"` // Retro-compatibility
|
||||||
@@ -44,11 +46,12 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
username: extraSettings.Username,
|
ipv6Suffix: ipv6Suffix,
|
||||||
clientKey: clientKey,
|
username: extraSettings.Username,
|
||||||
|
clientKey: clientKey,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,6 +86,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,15 +21,17 @@ import (
|
|||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
group string
|
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
|
group string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -49,6 +51,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
group: extraSettings.Group,
|
group: extraSettings.Group,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
@@ -89,6 +92,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -118,7 +125,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
values.Set("location", p.group)
|
values.Set("location", p.group)
|
||||||
hostname := utils.BuildDomainName(p.host, p.domain)
|
hostname := utils.BuildDomainName(p.host, p.domain)
|
||||||
values.Set("hostname", hostname)
|
values.Set("hostname", hostname)
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
if ip.Is6() {
|
if ip.Is6() {
|
||||||
values.Set("myipv6", ip.String())
|
values.Set("myipv6", ip.String())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -20,12 +20,14 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
token string
|
token string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
UseProviderIP bool `json:"provider_ip"`
|
UseProviderIP bool `json:"provider_ip"`
|
||||||
@@ -38,6 +40,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
}
|
}
|
||||||
@@ -74,6 +77,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -108,7 +115,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
values.Set("token", p.token)
|
values.Set("token", p.token)
|
||||||
values.Set("zone", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("zone", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
ipValue := ip.String()
|
ipValue := ip.String()
|
||||||
if p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if useProviderIP {
|
||||||
ipValue = "auto"
|
ipValue = "auto"
|
||||||
}
|
}
|
||||||
if isIPv4 {
|
if isIPv4 {
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
token string
|
token string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
@@ -42,6 +44,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -79,6 +82,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -106,7 +113,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
if p.host == "*" {
|
if p.host == "*" {
|
||||||
|
|||||||
@@ -19,14 +19,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
token string
|
ipv6Suffix netip.Prefix
|
||||||
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}{}
|
}{}
|
||||||
@@ -35,10 +37,11 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
token: extraSettings.Token,
|
ipv6Suffix: ipv6Suffix,
|
||||||
|
token: extraSettings.Token,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -74,6 +77,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) BuildDomainName() string {
|
func (p *Provider) BuildDomainName() string {
|
||||||
return utils.BuildDomainName(p.host, p.domain)
|
return utils.BuildDomainName(p.host, p.domain)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ttl int
|
ipVersion ipversion.IPVersion
|
||||||
ipVersion ipversion.IPVersion
|
ipv6Suffix netip.Prefix
|
||||||
|
ttl int
|
||||||
// Authentication, either use the personal access token
|
// Authentication, either use the personal access token
|
||||||
// or the deprecated API key.
|
// or the deprecated API key.
|
||||||
// See https://api.gandi.net/docs/authentication/
|
// See https://api.gandi.net/docs/authentication/
|
||||||
@@ -32,7 +33,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
PersonalAccessToken string `json:"personal_access_token"`
|
PersonalAccessToken string `json:"personal_access_token"`
|
||||||
APIKey string `json:"key"`
|
APIKey string `json:"key"`
|
||||||
@@ -46,6 +48,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
personalAccessToken: extraSettings.PersonalAccessToken,
|
personalAccessToken: extraSettings.PersonalAccessToken,
|
||||||
apiKey: extraSettings.APIKey,
|
apiKey: extraSettings.APIKey,
|
||||||
ttl: extraSettings.TTL,
|
ttl: extraSettings.TTL,
|
||||||
@@ -80,6 +83,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package gcp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
"github.com/qdm12/ddns-updater/internal/models"
|
"github.com/qdm12/ddns-updater/internal/models"
|
||||||
"github.com/qdm12/ddns-updater/internal/provider/constants"
|
"github.com/qdm12/ddns-updater/internal/provider/constants"
|
||||||
@@ -14,14 +15,16 @@ import (
|
|||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
project string
|
project string
|
||||||
zone string
|
zone string
|
||||||
credentials json.RawMessage
|
credentials json.RawMessage
|
||||||
ipVersion ipversion.IPVersion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
var extraSettings struct {
|
var extraSettings struct {
|
||||||
Project string `json:"project"`
|
Project string `json:"project"`
|
||||||
Zone string `json:"zone"`
|
Zone string `json:"zone"`
|
||||||
@@ -37,6 +40,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
project: extraSettings.Project,
|
project: extraSettings.Project,
|
||||||
zone: extraSettings.Zone,
|
zone: extraSettings.Zone,
|
||||||
credentials: extraSettings.Credentials,
|
credentials: extraSettings.Credentials,
|
||||||
@@ -82,6 +86,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
key string
|
ipv6Suffix netip.Prefix
|
||||||
secret string
|
key string
|
||||||
|
secret string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Secret string `json:"secret"`
|
Secret string `json:"secret"`
|
||||||
@@ -38,11 +40,12 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
key: extraSettings.Key,
|
ipv6Suffix: ipv6Suffix,
|
||||||
secret: extraSettings.Secret,
|
key: extraSettings.Key,
|
||||||
|
secret: extraSettings.Secret,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -80,6 +83,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,12 +23,14 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
UseProviderIP bool `json:"provider_ip"`
|
UseProviderIP bool `json:"provider_ip"`
|
||||||
@@ -41,6 +43,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
}
|
}
|
||||||
@@ -74,6 +77,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -101,7 +108,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", fqdn)
|
values.Set("hostname", fqdn)
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
@@ -147,7 +155,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
|
|
||||||
newIP = ips[0]
|
newIP = ips[0]
|
||||||
if !p.useProviderIP && ip.Compare(newIP) != 0 {
|
if !useProviderIP && ip.Compare(newIP) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
token string
|
token string
|
||||||
zoneIdentifier string
|
zoneIdentifier string
|
||||||
ttl uint
|
ttl uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
ZoneIdentifier string `json:"zone_identifier"`
|
ZoneIdentifier string `json:"zone_identifier"`
|
||||||
@@ -39,6 +41,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
zoneIdentifier: extraSettings.ZoneIdentifier,
|
zoneIdentifier: extraSettings.ZoneIdentifier,
|
||||||
ttl: extraSettings.TTL,
|
ttl: extraSettings.TTL,
|
||||||
@@ -79,6 +82,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -42,6 +44,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -81,6 +84,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -107,7 +114,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
@@ -152,7 +160,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: for response %q: %w",
|
return netip.Addr{}, fmt.Errorf("%w: for response %q: %w",
|
||||||
errors.ErrIPReceivedMalformed, ipString, err)
|
errors.ErrIPReceivedMalformed, ipString, err)
|
||||||
} else if !p.useProviderIP && ip.Compare(newIP) != 0 {
|
} else if !useProviderIP && ip.Compare(newIP) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
username string
|
ipv6Suffix netip.Prefix
|
||||||
password string
|
username string
|
||||||
|
password string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -37,11 +39,12 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, fmt.Errorf("decoding inwx extra settings: %w", err)
|
return nil, fmt.Errorf("decoding inwx extra settings: %w", err)
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
username: extraSettings.Username,
|
ipv6Suffix: ipv6Suffix,
|
||||||
password: extraSettings.Password,
|
username: extraSettings.Username,
|
||||||
|
password: extraSettings.Password,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -78,6 +81,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
apiKey string
|
ipv6Suffix netip.Prefix
|
||||||
|
apiKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
APIKey string `json:"api_key"`
|
APIKey string `json:"api_key"`
|
||||||
}{}
|
}{}
|
||||||
@@ -30,10 +32,11 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, fmt.Errorf("decoding ionos extra settings: %w", err)
|
return nil, fmt.Errorf("decoding ionos extra settings: %w", err)
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
apiKey: extraSettings.APIKey,
|
ipv6Suffix: ipv6Suffix,
|
||||||
|
apiKey: extraSettings.APIKey,
|
||||||
}
|
}
|
||||||
if err := p.isValid(); err != nil {
|
if err := p.isValid(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -64,6 +67,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,14 +20,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
token string
|
ipv6Suffix netip.Prefix
|
||||||
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}{}
|
}{}
|
||||||
@@ -36,10 +38,11 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
token: extraSettings.Token,
|
ipv6Suffix: ipv6Suffix,
|
||||||
|
token: extraSettings.Token,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -71,6 +74,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
email string
|
ipv6Suffix netip.Prefix
|
||||||
token string
|
email string
|
||||||
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
@@ -38,11 +40,12 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
email: extraSettings.Email,
|
ipv6Suffix: ipv6Suffix,
|
||||||
token: extraSettings.Token,
|
email: extraSettings.Email,
|
||||||
|
token: extraSettings.Token,
|
||||||
}
|
}
|
||||||
err = p.isValid()
|
err = p.isValid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -82,6 +85,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
username string
|
ipv6Suffix netip.Prefix
|
||||||
token string
|
username string
|
||||||
ttl *uint32
|
token string
|
||||||
|
ttl *uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
@@ -48,12 +50,13 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Provider{
|
return &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
username: extraSettings.Username,
|
ipv6Suffix: ipv6Suffix,
|
||||||
token: extraSettings.Token,
|
username: extraSettings.Username,
|
||||||
ttl: extraSettings.TTL,
|
token: extraSettings.Token,
|
||||||
|
ttl: extraSettings.TTL,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +76,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
customerNumber string
|
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
|
customerNumber string
|
||||||
apiKey string
|
apiKey string
|
||||||
password string
|
password string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
var extraSettings struct {
|
var extraSettings struct {
|
||||||
CustomerNumber string `json:"customer_number"`
|
CustomerNumber string `json:"customer_number"`
|
||||||
APIKey string `json:"api_key"`
|
APIKey string `json:"api_key"`
|
||||||
@@ -39,6 +41,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
customerNumber: extraSettings.CustomerNumber,
|
customerNumber: extraSettings.CustomerNumber,
|
||||||
apiKey: extraSettings.APIKey,
|
apiKey: extraSettings.APIKey,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
@@ -82,6 +85,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,14 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
key string
|
key string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
UseProviderIP bool `json:"provider_ip"`
|
UseProviderIP bool `json:"provider_ip"`
|
||||||
@@ -38,6 +40,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
key: extraSettings.Key,
|
key: extraSettings.Key,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
}
|
}
|
||||||
@@ -71,6 +74,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -98,7 +105,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
values.Set("h", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("h", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
values.Set("k", p.key)
|
values.Set("k", p.key)
|
||||||
updatingIP6 := ip.Is6()
|
updatingIP6 := ip.Is6()
|
||||||
if p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if useProviderIP {
|
||||||
values.Set("auto", "")
|
values.Set("auto", "")
|
||||||
} else {
|
} else {
|
||||||
if updatingIP6 {
|
if updatingIP6 {
|
||||||
@@ -147,7 +155,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
newIP, err = netip.ParseAddr(ipString)
|
newIP, err = netip.ParseAddr(ipString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: %w", errors.ErrIPReceivedMalformed, err)
|
return netip.Addr{}, fmt.Errorf("%w: %w", errors.ErrIPReceivedMalformed, err)
|
||||||
} else if !p.useProviderIP && ip.Compare(newIP) != 0 {
|
} else if !useProviderIP && ip.Compare(newIP) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -43,6 +45,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -85,6 +88,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -111,7 +118,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
if ip.Is6() {
|
if ip.Is6() {
|
||||||
values.Set("myipv6", ip.String())
|
values.Set("myipv6", ip.String())
|
||||||
} else {
|
} else {
|
||||||
@@ -170,12 +178,12 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
ips = ipextract.IPv6(s)
|
ips = ipextract.IPv6(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.useProviderIP && len(ips) == 0 {
|
if !useProviderIP && len(ips) == 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrReceivedNoIP)
|
return netip.Addr{}, fmt.Errorf("%w", errors.ErrReceivedNoIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
newIP = ips[0]
|
newIP = ips[0]
|
||||||
if !p.useProviderIP && ip.Compare(newIP) != 0 {
|
if !useProviderIP && ip.Compare(newIP) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,13 +21,15 @@ import (
|
|||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain string,
|
func New(data json.RawMessage, domain string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -40,6 +42,7 @@ func New(data json.RawMessage, domain string,
|
|||||||
p = &Provider{
|
p = &Provider{
|
||||||
domain: domain,
|
domain: domain,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -77,6 +80,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -104,7 +111,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
|
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", p.domain)
|
values.Set("hostname", p.domain)
|
||||||
if !p.useProviderIP {
|
if !p.useProviderIP || (ip.Is6() && p.ipv6Suffix.IsValid()) {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -42,6 +44,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -81,6 +84,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -107,7 +114,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
@@ -141,7 +149,7 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
newIP, err = netip.ParseAddr(responseIPString)
|
newIP, err = netip.ParseAddr(responseIPString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: %w", errors.ErrIPReceivedMalformed, err)
|
return netip.Addr{}, fmt.Errorf("%w: %w", errors.ErrIPReceivedMalformed, err)
|
||||||
} else if !p.useProviderIP && newIP.Compare(ip) != 0 {
|
} else if !useProviderIP && newIP.Compare(ip) != 0 {
|
||||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
@@ -36,7 +37,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -61,6 +63,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -117,6 +120,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -145,7 +152,8 @@ func (p *Provider) updateWithDynHost(ctx context.Context, client *http.Client,
|
|||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("system", "dyndns")
|
values.Set("system", "dyndns")
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
|
|||||||
@@ -18,14 +18,16 @@ import (
|
|||||||
type Provider struct {
|
type Provider struct {
|
||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ttl uint
|
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
|
ttl uint
|
||||||
apiKey string
|
apiKey string
|
||||||
secretAPIKey string
|
secretAPIKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
SecretAPIKey string `json:"secret_api_key"`
|
SecretAPIKey string `json:"secret_api_key"`
|
||||||
APIKey string `json:"api_key"`
|
APIKey string `json:"api_key"`
|
||||||
@@ -39,6 +41,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
secretAPIKey: extraSettings.SecretAPIKey,
|
secretAPIKey: extraSettings.SecretAPIKey,
|
||||||
apiKey: extraSettings.APIKey,
|
apiKey: extraSettings.APIKey,
|
||||||
ttl: extraSettings.TTL,
|
ttl: extraSettings.TTL,
|
||||||
@@ -76,6 +79,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -42,6 +44,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -81,6 +84,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -107,7 +114,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
ttl uint
|
ttl uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string, ipVersion ipversion.IPVersion) (
|
func New(data json.RawMessage, domain, host string, ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
p *Provider, err error) {
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
@@ -45,6 +46,7 @@ func New(data json.RawMessage, domain, host string, ipVersion ipversion.IPVersio
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -85,6 +87,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
user string
|
user string
|
||||||
password string
|
password string
|
||||||
token string
|
token string
|
||||||
@@ -29,7 +30,8 @@ type Provider struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -44,6 +46,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
user: extraSettings.User,
|
user: extraSettings.User,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
@@ -88,6 +91,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
UseProviderIP bool `json:"provider_ip"`
|
UseProviderIP bool `json:"provider_ip"`
|
||||||
@@ -40,6 +42,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
}
|
}
|
||||||
@@ -76,6 +79,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -102,7 +109,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
u.RawQuery = values.Encode()
|
u.RawQuery = values.Encode()
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
email string
|
email string
|
||||||
password string
|
password string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@@ -42,6 +44,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
email: extraSettings.Email,
|
email: extraSettings.Email,
|
||||||
password: extraSettings.Password,
|
password: extraSettings.Password,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -81,6 +84,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -100,7 +107,8 @@ func (p *Provider) HTML() models.HTMLRow {
|
|||||||
|
|
||||||
func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Addr) (newIP netip.Addr, err error) {
|
func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Addr) (newIP netip.Addr, err error) {
|
||||||
host := "dyndns.variomedia.de"
|
host := "dyndns.variomedia.de"
|
||||||
if p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if useProviderIP {
|
||||||
if ip.Is6() {
|
if ip.Is6() {
|
||||||
host = "dyndns6.variomedia.de"
|
host = "dyndns6.variomedia.de"
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -23,13 +23,15 @@ type Provider struct {
|
|||||||
domain string
|
domain string
|
||||||
host string
|
host string
|
||||||
ipVersion ipversion.IPVersion
|
ipVersion ipversion.IPVersion
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
username string
|
username string
|
||||||
token string
|
token string
|
||||||
useProviderIP bool
|
useProviderIP bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(data json.RawMessage, domain, host string,
|
func New(data json.RawMessage, domain, host string,
|
||||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
ipVersion ipversion.IPVersion, ipv6Suffix netip.Prefix) (
|
||||||
|
p *Provider, err error) {
|
||||||
extraSettings := struct {
|
extraSettings := struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
@@ -43,6 +45,7 @@ func New(data json.RawMessage, domain, host string,
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
host: host,
|
host: host,
|
||||||
ipVersion: ipVersion,
|
ipVersion: ipVersion,
|
||||||
|
ipv6Suffix: ipv6Suffix,
|
||||||
username: extraSettings.Username,
|
username: extraSettings.Username,
|
||||||
token: extraSettings.Token,
|
token: extraSettings.Token,
|
||||||
useProviderIP: extraSettings.UseProviderIP,
|
useProviderIP: extraSettings.UseProviderIP,
|
||||||
@@ -80,6 +83,10 @@ func (p *Provider) IPVersion() ipversion.IPVersion {
|
|||||||
return p.ipVersion
|
return p.ipVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) IPv6Suffix() netip.Prefix {
|
||||||
|
return p.ipv6Suffix
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) Proxied() bool {
|
func (p *Provider) Proxied() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -107,7 +114,8 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Add
|
|||||||
}
|
}
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
values.Set("hostname", utils.BuildURLQueryHostname(p.host, p.domain))
|
||||||
if !p.useProviderIP {
|
useProviderIP := p.useProviderIP && (ip.Is4() || !p.ipv6Suffix.IsValid())
|
||||||
|
if !useProviderIP {
|
||||||
values.Set("myip", ip.String())
|
values.Set("myip", ip.String())
|
||||||
}
|
}
|
||||||
if p.host == "*" {
|
if p.host == "*" {
|
||||||
|
|||||||
27
internal/update/ipv6.go
Normal file
27
internal/update/ipv6.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package update
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ipv6WithSuffix(publicIP netip.Addr, ipv6Suffix netip.Prefix) (
|
||||||
|
updateIP netip.Addr) {
|
||||||
|
if !publicIP.IsValid() || !publicIP.Is6() || !ipv6Suffix.IsValid() {
|
||||||
|
return publicIP
|
||||||
|
}
|
||||||
|
|
||||||
|
const ipv6Bits = 128
|
||||||
|
const bitsInByte = 8
|
||||||
|
prefixLength := (ipv6Bits - ipv6Suffix.Bits()) / bitsInByte
|
||||||
|
ispPrefix := publicIP.AsSlice()[:prefixLength]
|
||||||
|
localSuffix := ipv6Suffix.Addr().AsSlice()[prefixLength:]
|
||||||
|
ipv6Bytes := ispPrefix // ispPrefix has already 16 bytes of capacity
|
||||||
|
ipv6Bytes = append(ipv6Bytes, localSuffix...)
|
||||||
|
updateIP, ok := netip.AddrFromSlice(ipv6Bytes)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("failed to create IPv6 address from merged bytes %v", ipv6Bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateIP
|
||||||
|
}
|
||||||
57
internal/update/ipv6_test.go
Normal file
57
internal/update/ipv6_test.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package update
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_ipv6WithSuffix(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
testCases := map[string]struct {
|
||||||
|
publicIP netip.Addr
|
||||||
|
ipv6Suffix netip.Prefix
|
||||||
|
updateIP netip.Addr
|
||||||
|
}{
|
||||||
|
"blank_inputs": {},
|
||||||
|
"ipv4_publicip": {
|
||||||
|
publicIP: netip.MustParseAddr("1.2.3.4"),
|
||||||
|
updateIP: netip.MustParseAddr("1.2.3.4"),
|
||||||
|
},
|
||||||
|
"invalid_suffix": {
|
||||||
|
publicIP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
updateIP: netip.MustParseAddr("2001:db8::1"),
|
||||||
|
},
|
||||||
|
"zero_suffix": {
|
||||||
|
publicIP: netip.MustParseAddr("e4db:af36:82e:1221:1b7f:2f54:6e9e:5e5f"),
|
||||||
|
ipv6Suffix: netip.MustParsePrefix("0:0:0:0:0:0:0:0/0"),
|
||||||
|
updateIP: netip.MustParseAddr("e4db:af36:82e:1221:1b7f:2f54:6e9e:5e5f"),
|
||||||
|
},
|
||||||
|
"suffix_64": {
|
||||||
|
publicIP: netip.MustParseAddr("e4db:af36:82e:1221:1b7f:2f54:6e9e:5e5f"),
|
||||||
|
ipv6Suffix: netip.MustParsePrefix("0:0:0:0:72ad:8fbb:a54e:bedd/64"),
|
||||||
|
updateIP: netip.MustParseAddr("e4db:af36:82e:1221:" + "72ad:8fbb:a54e:bedd"),
|
||||||
|
},
|
||||||
|
"suffix_56": {
|
||||||
|
publicIP: netip.MustParseAddr("e4db:af36:82e:1221:1b7f:2f54:6e9e:5e5f"),
|
||||||
|
ipv6Suffix: netip.MustParsePrefix("bbff:8199:4e2f:b4ba:72ad:8fbb:a54e:bedd/56"),
|
||||||
|
updateIP: netip.MustParseAddr("e4db:af36:82e:1221:1b" + "ad:8fbb:a54e:bedd"),
|
||||||
|
},
|
||||||
|
"suffix_48": {
|
||||||
|
publicIP: netip.MustParseAddr("e4db:af36:82e:1221:1b7f:2f54:6e9e:5e5f"),
|
||||||
|
ipv6Suffix: netip.MustParsePrefix("bbff:8199:4e2f:b4ba:72ad:8fbb:a54e:bedd/48"),
|
||||||
|
updateIP: netip.MustParseAddr("e4db:af36:82e:1221:1b7f:" + "8fbb:a54e:bedd"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
updateIP := ipv6WithSuffix(testCase.publicIP, testCase.ipv6Suffix)
|
||||||
|
assert.Equal(t, testCase.updateIP.String(), updateIP.String())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package update
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/netip"
|
|
||||||
)
|
|
||||||
|
|
||||||
func mustMaskIPv6(ipv6 netip.Addr, ipv6MaskBits uint8) (maskedIPv6 netip.Addr) {
|
|
||||||
prefix, err := ipv6.Prefix(int(ipv6MaskBits))
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("getting masked IPv6 prefix: %s", err))
|
|
||||||
}
|
|
||||||
maskedIPv6 = prefix.Addr()
|
|
||||||
return maskedIPv6
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package update
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/netip"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_mustMaskIPv6(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
const maskBits = 24
|
|
||||||
ip := netip.AddrFrom4([4]byte{1, 2, 3, 4})
|
|
||||||
maskedIP := mustMaskIPv6(ip, maskBits)
|
|
||||||
|
|
||||||
expected := netip.AddrFrom4([4]byte{1, 2, 3, 0})
|
|
||||||
assert.Equal(t, expected, maskedIP)
|
|
||||||
}
|
|
||||||
@@ -14,37 +14,34 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Runner struct {
|
type Runner struct {
|
||||||
period time.Duration
|
period time.Duration
|
||||||
db Database
|
db Database
|
||||||
updater UpdaterInterface
|
updater UpdaterInterface
|
||||||
force chan struct{}
|
force chan struct{}
|
||||||
forceResult chan []error
|
forceResult chan []error
|
||||||
ipv6MaskBits uint8
|
cooldown time.Duration
|
||||||
cooldown time.Duration
|
resolver LookupIPer
|
||||||
resolver LookupIPer
|
ipGetter PublicIPFetcher
|
||||||
ipGetter PublicIPFetcher
|
logger Logger
|
||||||
logger Logger
|
timeNow func() time.Time
|
||||||
timeNow func() time.Time
|
hioClient HealthchecksIOClient
|
||||||
hioClient HealthchecksIOClient
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRunner(db Database, updater UpdaterInterface, ipGetter PublicIPFetcher,
|
func NewRunner(db Database, updater UpdaterInterface, ipGetter PublicIPFetcher,
|
||||||
period time.Duration, ipv6MaskBits uint8, cooldown time.Duration,
|
period time.Duration, cooldown time.Duration, logger Logger, resolver LookupIPer,
|
||||||
logger Logger, resolver LookupIPer, timeNow func() time.Time,
|
timeNow func() time.Time, hioClient HealthchecksIOClient) *Runner {
|
||||||
hioClient HealthchecksIOClient) *Runner {
|
|
||||||
return &Runner{
|
return &Runner{
|
||||||
period: period,
|
period: period,
|
||||||
db: db,
|
db: db,
|
||||||
updater: updater,
|
updater: updater,
|
||||||
force: make(chan struct{}),
|
force: make(chan struct{}),
|
||||||
forceResult: make(chan []error),
|
forceResult: make(chan []error),
|
||||||
ipv6MaskBits: ipv6MaskBits,
|
cooldown: cooldown,
|
||||||
cooldown: cooldown,
|
resolver: resolver,
|
||||||
resolver: resolver,
|
ipGetter: ipGetter,
|
||||||
ipGetter: ipGetter,
|
logger: logger,
|
||||||
logger: logger,
|
timeNow: timeNow,
|
||||||
timeNow: timeNow,
|
hioClient: hioClient,
|
||||||
hioClient: hioClient,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,15 +100,13 @@ func doIPVersion(records []librecords.Record) (doIP, doIPv4, doIPv6 bool) {
|
|||||||
return doIP, doIPv4, doIPv6
|
return doIP, doIPv4, doIPv6
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) getNewIPs(ctx context.Context, doIP, doIPv4, doIPv6 bool, ipv6MaskBits uint8) (
|
func (r *Runner) getNewIPs(ctx context.Context, doIP, doIPv4, doIPv6 bool) (
|
||||||
ip, ipv4, ipv6 netip.Addr, errors []error) {
|
ip, ipv4, ipv6 netip.Addr, errors []error) {
|
||||||
var err error
|
var err error
|
||||||
if doIP {
|
if doIP {
|
||||||
ip, err = tryAndRepeatGettingIP(ctx, r.ipGetter.IP, r.logger, ipversion.IP4or6)
|
ip, err = tryAndRepeatGettingIP(ctx, r.ipGetter.IP, r.logger, ipversion.IP4or6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors = append(errors, err)
|
errors = append(errors, err)
|
||||||
} else if ip.Is6() {
|
|
||||||
ip = mustMaskIPv6(ip, ipv6MaskBits)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if doIPv4 {
|
if doIPv4 {
|
||||||
@@ -124,18 +119,17 @@ func (r *Runner) getNewIPs(ctx context.Context, doIP, doIPv4, doIPv6 bool, ipv6M
|
|||||||
ipv6, err = tryAndRepeatGettingIP(ctx, r.ipGetter.IP6, r.logger, ipversion.IP6)
|
ipv6, err = tryAndRepeatGettingIP(ctx, r.ipGetter.IP6, r.logger, ipversion.IP6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors = append(errors, err)
|
errors = append(errors, err)
|
||||||
} else {
|
|
||||||
ipv6 = mustMaskIPv6(ipv6, ipv6MaskBits)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ip, ipv4, ipv6, errors
|
return ip, ipv4, ipv6, errors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) getRecordIDsToUpdate(ctx context.Context, records []librecords.Record,
|
func (r *Runner) getRecordIDsToUpdate(ctx context.Context, records []librecords.Record,
|
||||||
ip, ipv4, ipv6 netip.Addr, now time.Time, ipv6MaskBits uint8) (recordIDs map[uint]struct{}) {
|
ip, ipv4, ipv6 netip.Addr, now time.Time) (recordIDs map[uint]struct{}) {
|
||||||
recordIDs = make(map[uint]struct{})
|
recordIDs = make(map[uint]struct{})
|
||||||
for i, record := range records {
|
for i, record := range records {
|
||||||
if shouldUpdate := r.shouldUpdateRecord(ctx, record, ip, ipv4, ipv6, now, ipv6MaskBits); shouldUpdate {
|
shouldUpdate := r.shouldUpdateRecord(ctx, record, ip, ipv4, ipv6, now)
|
||||||
|
if shouldUpdate {
|
||||||
id := uint(i)
|
id := uint(i)
|
||||||
recordIDs[id] = struct{}{}
|
recordIDs[id] = struct{}{}
|
||||||
}
|
}
|
||||||
@@ -144,7 +138,7 @@ func (r *Runner) getRecordIDsToUpdate(ctx context.Context, records []librecords.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) shouldUpdateRecord(ctx context.Context, record librecords.Record,
|
func (r *Runner) shouldUpdateRecord(ctx context.Context, record librecords.Record,
|
||||||
ip, ipv4, ipv6 netip.Addr, now time.Time, ipv6MaskBits uint8) (update bool) {
|
ip, ipv4, ipv6 netip.Addr, now time.Time) (update bool) {
|
||||||
isWithinBanPeriod := record.LastBan != nil && now.Sub(*record.LastBan) < time.Hour
|
isWithinBanPeriod := record.LastBan != nil && now.Sub(*record.LastBan) < time.Hour
|
||||||
isWithinCooldown := now.Sub(record.History.GetSuccessTime()) < r.cooldown
|
isWithinCooldown := now.Sub(record.History.GetSuccessTime()) < r.cooldown
|
||||||
if isWithinBanPeriod || isWithinCooldown {
|
if isWithinBanPeriod || isWithinCooldown {
|
||||||
@@ -161,13 +155,15 @@ func (r *Runner) shouldUpdateRecord(ctx context.Context, record librecords.Recor
|
|||||||
r.logger.Warn(fmt.Sprintf("Skipping update for %s because %s address was not found",
|
r.logger.Warn(fmt.Sprintf("Skipping update for %s because %s address was not found",
|
||||||
hostname, ipVersionToIPKind(ipVersion)))
|
hostname, ipVersionToIPKind(ipVersion)))
|
||||||
return false
|
return false
|
||||||
|
} else if publicIP.Is6() {
|
||||||
|
publicIP = ipv6WithSuffix(publicIP, record.Provider.IPv6Suffix())
|
||||||
}
|
}
|
||||||
|
|
||||||
if record.Provider.Proxied() {
|
if record.Provider.Proxied() {
|
||||||
lastIP := record.History.GetCurrentIP() // can be nil
|
lastIP := record.History.GetCurrentIP() // can be nil
|
||||||
return r.shouldUpdateRecordNoLookup(hostname, ipVersion, lastIP, publicIP)
|
return r.shouldUpdateRecordNoLookup(hostname, ipVersion, lastIP, publicIP)
|
||||||
}
|
}
|
||||||
return r.shouldUpdateRecordWithLookup(ctx, hostname, ipVersion, publicIP, ipv6MaskBits)
|
return r.shouldUpdateRecordWithLookup(ctx, hostname, ipVersion, publicIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) shouldUpdateRecordNoLookup(hostname string, ipVersion ipversion.IPVersion,
|
func (r *Runner) shouldUpdateRecordNoLookup(hostname string, ipVersion ipversion.IPVersion,
|
||||||
@@ -181,8 +177,8 @@ func (r *Runner) shouldUpdateRecordNoLookup(hostname string, ipVersion ipversion
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) shouldUpdateRecordWithLookup(ctx context.Context, hostname string, ipVersion ipversion.IPVersion,
|
func (r *Runner) shouldUpdateRecordWithLookup(ctx context.Context, hostname string,
|
||||||
publicIP netip.Addr, ipv6MaskBits uint8) (update bool) {
|
ipVersion ipversion.IPVersion, publicIP netip.Addr) (update bool) {
|
||||||
const tries = 5
|
const tries = 5
|
||||||
recordIPv4, recordIPv6, err := r.lookupIPsResilient(ctx, hostname, tries)
|
recordIPv4, recordIPv6, err := r.lookupIPsResilient(ctx, hostname, tries)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -195,10 +191,6 @@ func (r *Runner) shouldUpdateRecordWithLookup(ctx context.Context, hostname stri
|
|||||||
fmt.Sprint(tries) + " tries: " + err.Error()) // update anyway
|
fmt.Sprint(tries) + " tries: " + err.Error()) // update anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
if recordIPv6.IsValid() {
|
|
||||||
recordIPv6 = mustMaskIPv6(recordIPv6, ipv6MaskBits)
|
|
||||||
}
|
|
||||||
|
|
||||||
ipKind := ipVersionToIPKind(ipVersion)
|
ipKind := ipVersionToIPKind(ipVersion)
|
||||||
recordIP := recordIPv4
|
recordIP := recordIPv4
|
||||||
if publicIP.Is6() {
|
if publicIP.Is6() {
|
||||||
@@ -249,18 +241,18 @@ func setInitialUpToDateStatus(db Database, id uint, updateIP netip.Addr, now tim
|
|||||||
return db.Update(id, record)
|
return db.Update(id, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Runner) updateNecessary(ctx context.Context, ipv6MaskBits uint8) (errors []error) {
|
func (r *Runner) updateNecessary(ctx context.Context) (errors []error) {
|
||||||
records := r.db.SelectAll()
|
records := r.db.SelectAll()
|
||||||
doIP, doIPv4, doIPv6 := doIPVersion(records)
|
doIP, doIPv4, doIPv6 := doIPVersion(records)
|
||||||
r.logger.Debug(fmt.Sprintf("configured to fetch IP: v4 or v6: %t, v4: %t, v6: %t", doIP, doIPv4, doIPv6))
|
r.logger.Debug(fmt.Sprintf("configured to fetch IP: v4 or v6: %t, v4: %t, v6: %t", doIP, doIPv4, doIPv6))
|
||||||
ip, ipv4, ipv6, errors := r.getNewIPs(ctx, doIP, doIPv4, doIPv6, ipv6MaskBits)
|
ip, ipv4, ipv6, errors := r.getNewIPs(ctx, doIP, doIPv4, doIPv6)
|
||||||
r.logger.Debug(fmt.Sprintf("your public IP address are: v4 or v6: %s, v4: %s, v6: %s", ip, ipv4, ipv6))
|
r.logger.Debug(fmt.Sprintf("your public IP address are: v4 or v6: %s, v4: %s, v6: %s", ip, ipv4, ipv6))
|
||||||
for _, err := range errors {
|
for _, err := range errors {
|
||||||
r.logger.Error(err.Error())
|
r.logger.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
now := r.timeNow()
|
now := r.timeNow()
|
||||||
recordIDs := r.getRecordIDsToUpdate(ctx, records, ip, ipv4, ipv6, now, ipv6MaskBits)
|
recordIDs := r.getRecordIDsToUpdate(ctx, records, ip, ipv4, ipv6, now)
|
||||||
|
|
||||||
for i, record := range records {
|
for i, record := range records {
|
||||||
id := uint(i)
|
id := uint(i)
|
||||||
@@ -269,6 +261,10 @@ func (r *Runner) updateNecessary(ctx context.Context, ipv6MaskBits uint8) (error
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
updateIP := getIPMatchingVersion(ip, ipv4, ipv6, record.Provider.IPVersion())
|
updateIP := getIPMatchingVersion(ip, ipv4, ipv6, record.Provider.IPVersion())
|
||||||
|
if updateIP.Is6() {
|
||||||
|
updateIP = ipv6WithSuffix(updateIP, record.Provider.IPv6Suffix())
|
||||||
|
}
|
||||||
|
|
||||||
err := setInitialUpToDateStatus(r.db, id, updateIP, now)
|
err := setInitialUpToDateStatus(r.db, id, updateIP, now)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("setting initial up to date status: %w", err)
|
err = fmt.Errorf("setting initial up to date status: %w", err)
|
||||||
@@ -284,6 +280,8 @@ func (r *Runner) updateNecessary(ctx context.Context, ipv6MaskBits uint8) (error
|
|||||||
errors = append(errors, err)
|
errors = append(errors, err)
|
||||||
r.logger.Error(err.Error())
|
r.logger.Error(err.Error())
|
||||||
continue
|
continue
|
||||||
|
} else if updateIP.Is6() {
|
||||||
|
updateIP = ipv6WithSuffix(updateIP, record.Provider.IPv6Suffix())
|
||||||
}
|
}
|
||||||
r.logger.Info("Updating record " + record.Provider.String() + " to use " + updateIP.String())
|
r.logger.Info("Updating record " + record.Provider.String() + " to use " + updateIP.String())
|
||||||
err := r.updater.Update(ctx, id, updateIP, r.timeNow())
|
err := r.updater.Update(ctx, id, updateIP, r.timeNow())
|
||||||
@@ -307,9 +305,9 @@ func (r *Runner) Run(ctx context.Context, done chan<- struct{}) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
r.updateNecessary(ctx, r.ipv6MaskBits)
|
r.updateNecessary(ctx)
|
||||||
case <-r.force:
|
case <-r.force:
|
||||||
r.forceResult <- r.updateNecessary(ctx, r.ipv6MaskBits)
|
r.forceResult <- r.updateNecessary(ctx)
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user