diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4de38dd..99821349 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -46,6 +46,8 @@ and this project adheres to
### Changed
+- DHCP gateway address, subnet mask, IP address range, and leases validations
+ ([#3529]).
- The `systemd` service script will now create the `/var/log` directory when it
doesn't exist ([#3579]).
- Items in allowed clients, disallowed clients, and blocked hosts lists are now
@@ -196,6 +198,7 @@ In this release, the schema version has changed from 10 to 12.
[#3450]: https://github.com/AdguardTeam/AdGuardHome/issues/3450
[#3457]: https://github.com/AdguardTeam/AdGuardHome/issues/3457
[#3506]: https://github.com/AdguardTeam/AdGuardHome/issues/3506
+[#3529]: https://github.com/AdguardTeam/AdGuardHome/issues/3529
[#3538]: https://github.com/AdguardTeam/AdGuardHome/issues/3538
[#3551]: https://github.com/AdguardTeam/AdGuardHome/issues/3551
[#3564]: https://github.com/AdguardTeam/AdGuardHome/issues/3564
diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index f3d8abcd..6db195fe 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -37,6 +37,9 @@
"dhcp_ipv6_settings": "DHCP IPv6 Settings",
"form_error_required": "Required field",
"form_error_ip4_format": "Invalid IPv4 format",
+ "form_error_ip4_range_start_format": "Invalid range start IPv4 format",
+ "form_error_ip4_range_end_format": "Invalid range end IPv4 format",
+ "form_error_ip4_gateway_format": "Invalid gateway IPv4 format",
"form_error_ip6_format": "Invalid IPv6 format",
"form_error_ip_format": "Invalid IP format",
"form_error_mac_format": "Invalid MAC format",
@@ -45,7 +48,14 @@
"form_error_subnet": "Subnet \"{{cidr}}\" does not contain the IP address \"{{ip}}\"",
"form_error_positive": "Must be greater than 0",
"form_error_negative": "Must be equal to 0 or greater",
- "range_end_error": "Must be greater than range start",
+ "out_of_range_error": "Must be out of range \"{{start}}\"-\"{{end}}\"",
+ "in_range_error": "Must be in range \"{{start}}\"-\"{{end}}\"",
+ "lower_range_start_error": "Must be lower than range start",
+ "lower_range_end_error": "Must be lower than range end",
+ "greater_range_start_error": "Must be greater than range start",
+ "greater_range_end_error": "Must be greater than range end",
+ "subnet_error": "Addresses must be in one subnet",
+ "gateway_or_subnet_invalid": "Subnet mask invalid",
"dhcp_form_gateway_input": "Gateway IP",
"dhcp_form_subnet_input": "Subnet mask",
"dhcp_form_range_title": "Range of IP addresses",
diff --git a/client/src/components/Settings/Dhcp/FormDHCPv4.js b/client/src/components/Settings/Dhcp/FormDHCPv4.js
index 873e7696..cb371f9f 100644
--- a/client/src/components/Settings/Dhcp/FormDHCPv4.js
+++ b/client/src/components/Settings/Dhcp/FormDHCPv4.js
@@ -13,6 +13,9 @@ import {
validateIpv4,
validateRequiredValue,
validateIpv4RangeEnd,
+ validateGatewaySubnetMask,
+ validateIpForGatewaySubnetMask,
+ validateNotInRange,
} from '../../../helpers/validators';
const FormDHCPv4 = ({
@@ -54,7 +57,11 @@ const FormDHCPv4 = ({
type="text"
className="form-control"
placeholder={t(ipv4placeholders.gateway_ip)}
- validate={[validateIpv4, validateRequired]}
+ validate={[
+ validateIpv4,
+ validateRequired,
+ validateNotInRange,
+ ]}
disabled={!isInterfaceIncludesIpv4}
/>
@@ -66,7 +73,11 @@ const FormDHCPv4 = ({
type="text"
className="form-control"
placeholder={t(ipv4placeholders.subnet_mask)}
- validate={[validateIpv4, validateRequired]}
+ validate={[
+ validateIpv4,
+ validateRequired,
+ validateGatewaySubnetMask,
+ ]}
disabled={!isInterfaceIncludesIpv4}
/>
@@ -84,7 +95,11 @@ const FormDHCPv4 = ({
type="text"
className="form-control"
placeholder={t(ipv4placeholders.range_start)}
- validate={[validateIpv4]}
+ validate={[
+ validateIpv4,
+ validateGatewaySubnetMask,
+ validateIpForGatewaySubnetMask,
+ ]}
disabled={!isInterfaceIncludesIpv4}
/>
@@ -95,7 +110,12 @@ const FormDHCPv4 = ({
type="text"
className="form-control"
placeholder={t(ipv4placeholders.range_end)}
- validate={[validateIpv4, validateIpv4RangeEnd]}
+ validate={[
+ validateIpv4,
+ validateIpv4RangeEnd,
+ validateGatewaySubnetMask,
+ validateIpForGatewaySubnetMask,
+ ]}
disabled={!isInterfaceIncludesIpv4}
/>
diff --git a/client/src/components/Settings/Dhcp/StaticLeases/Form.js b/client/src/components/Settings/Dhcp/StaticLeases/Form.js
index e857144d..7e9c641b 100644
--- a/client/src/components/Settings/Dhcp/StaticLeases/Form.js
+++ b/client/src/components/Settings/Dhcp/StaticLeases/Form.js
@@ -10,6 +10,7 @@ import {
validateMac,
validateRequiredValue,
validateIpv4InCidr,
+ validateInRange,
} from '../../../../helpers/validators';
import { FORM_NAME } from '../../../../helpers/constants';
import { toggleLeaseModal } from '../../../../actions';
@@ -53,7 +54,12 @@ const Form = ({
type="text"
className="form-control"
placeholder={t('form_enter_subnet_ip', { cidr })}
- validate={[validateRequiredValue, validateIpv4, validateIpv4InCidr]}
+ validate={[
+ validateRequiredValue,
+ validateIpv4,
+ validateIpv4InCidr,
+ validateInRange,
+ ]}
/>
diff --git a/client/src/components/Settings/Dhcp/StaticLeases/Modal.js b/client/src/components/Settings/Dhcp/StaticLeases/Modal.js
index b65c298e..8ad0f009 100644
--- a/client/src/components/Settings/Dhcp/StaticLeases/Modal.js
+++ b/client/src/components/Settings/Dhcp/StaticLeases/Modal.js
@@ -11,6 +11,8 @@ const Modal = ({
handleSubmit,
processingAdding,
cidr,
+ rangeStart,
+ rangeEnd,
}) => {
const dispatch = useDispatch();
@@ -38,10 +40,14 @@ const Modal = ({
ip: '',
hostname: '',
cidr,
+ rangeStart,
+ rangeEnd,
}}
onSubmit={handleSubmit}
processingAdding={processingAdding}
cidr={cidr}
+ rangeStart={rangeStart}
+ rangeEnd={rangeEnd}
/>
@@ -53,6 +59,8 @@ Modal.propTypes = {
handleSubmit: PropTypes.func.isRequired,
processingAdding: PropTypes.bool.isRequired,
cidr: PropTypes.string.isRequired,
+ rangeStart: PropTypes.string,
+ rangeEnd: PropTypes.string,
};
export default withTranslation()(Modal);
diff --git a/client/src/components/Settings/Dhcp/StaticLeases/index.js b/client/src/components/Settings/Dhcp/StaticLeases/index.js
index 6e12f30e..bdd7cec5 100644
--- a/client/src/components/Settings/Dhcp/StaticLeases/index.js
+++ b/client/src/components/Settings/Dhcp/StaticLeases/index.js
@@ -22,6 +22,8 @@ const StaticLeases = ({
processingDeleting,
staticLeases,
cidr,
+ rangeStart,
+ rangeEnd,
}) => {
const [t] = useTranslation();
const dispatch = useDispatch();
@@ -100,6 +102,8 @@ const StaticLeases = ({
handleSubmit={handleSubmit}
processingAdding={processingAdding}
cidr={cidr}
+ rangeStart={rangeStart}
+ rangeEnd={rangeEnd}
/>
>
);
@@ -111,6 +115,8 @@ StaticLeases.propTypes = {
processingAdding: PropTypes.bool.isRequired,
processingDeleting: PropTypes.bool.isRequired,
cidr: PropTypes.string.isRequired,
+ rangeStart: PropTypes.string,
+ rangeEnd: PropTypes.string,
};
cellWrap.propTypes = {
diff --git a/client/src/components/Settings/Dhcp/index.js b/client/src/components/Settings/Dhcp/index.js
index 844e662e..6208d4a6 100644
--- a/client/src/components/Settings/Dhcp/index.js
+++ b/client/src/components/Settings/Dhcp/index.js
@@ -275,6 +275,8 @@ const Dhcp = () => {
processingAdding={processingAdding}
processingDeleting={processingDeleting}
cidr={cidr}
+ rangeStart={dhcp?.values?.v4?.range_start}
+ rangeEnd={dhcp?.values?.v4?.range_end}
/>