{"record":{"id":"8a4153caa7158ec3","repo":"TechnitiumSoftware/DnsServer","slug":"starting-address-cannot-be-same-as-the-network-add","errorCode":null,"errorMessage":"Starting address cannot be same as the network address.","messagePattern":"Starting address cannot be same as the network address\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dhcp/Scope.cs","lineNumber":1459,"sourceCode":"                throw new ArgumentException(\"The address must be an IPv4 address: \" + subnetMask.ToString(), nameof(subnetMask));\n\n            uint startingAddressNumber = startingAddress.ConvertIpToNumber();\n            uint endingAddressNumber = endingAddress.ConvertIpToNumber();\n\n            if (startingAddressNumber >= endingAddressNumber)\n                throw new ArgumentException(\"Ending address must be greater than starting address.\");\n\n            _startingAddress = startingAddress;\n            _endingAddress = endingAddress;\n            _subnetMask = subnetMask;\n\n            //compute other parameters\n            uint subnetMaskNumber = _subnetMask.ConvertIpToNumber();\n            uint networkAddressNumber = startingAddressNumber & subnetMaskNumber;\n            uint broadcastAddressNumber = networkAddressNumber | ~subnetMaskNumber;\n\n            if (networkAddressNumber == startingAddressNumber)\n                throw new ArgumentException(\"Starting address cannot be same as the network address.\");\n\n            if (broadcastAddressNumber == endingAddressNumber)\n                throw new ArgumentException(\"Ending address cannot be same as the broadcast address.\");\n\n            _networkAddress = IPAddressExtensions.ConvertNumberToIp(networkAddressNumber);\n            _broadcastAddress = IPAddressExtensions.ConvertNumberToIp(broadcastAddressNumber);\n\n            _lastAddressOfferedLock.Wait();\n            try\n            {\n                _lastAddressOffered = IPAddressExtensions.ConvertNumberToIp(startingAddressNumber - 1u);\n            }\n            finally\n            {\n                _lastAddressOfferedLock.Release();\n            }\n        }\n","sourceCodeStart":1441,"sourceCodeEnd":1477,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dhcp/Scope.cs#L1441-L1477","documentation":"Thrown by Scope construction / ChangeNetwork when the starting address equals the network address (start AND subnetMask). A DHCP pool must never offer the network identifier itself (e.g. 192.168.1.0/24) to a client, so the library rejects it up front.","triggerScenarios":"Passing a startingAddress that is the subnet's base address: e.g. start=192.168.1.0 with mask 255.255.255.0, or start=10.0.0.0 with mask 255.0.0.0. Also triggered when a /31 or /32 mask collapses network onto the supplied start, or when auto-generating start from the network address without incrementing.","commonSituations":"Generating ranges from CIDR notation but forgetting to skip the network address; config files that list the subnet base as the first usable host; tooling that sets start = networkAddress verbatim.","solutions":["Increment the starting address above the network address (network + 1) before constructing the Scope.","Recompute: if (start & mask) == start, bump start by one host.","For very small subnets (/31, /32) use a larger block since there are no usable hosts between network and broadcast.","Validate the mask itself; a malformed mask with all-zero host bits makes every address equal the network address."],"exampleFix":"// before\nvar net = IPAddress.Parse(\"192.168.1.0\");\nvar scope = new Scope(name, true, net,\n    IPAddress.Parse(\"192.168.1.254\"),\n    IPAddress.Parse(\"255.255.255.0\"), log, dhcpServer); // throws\n\n// after\nvar start = IPAddress.Parse(\"192.168.1.1\"); // network + 1\nvar scope = new Scope(name, true, start,\n    IPAddress.Parse(\"192.168.1.254\"),\n    IPAddress.Parse(\"255.255.255.0\"), log, dhcpServer);","handlingStrategy":"validation","validationCode":"static uint ToUint(IPAddress a){ var b=a.GetAddressBytes(); return (uint)((b[0]<<24)|(b[1]<<16)|(b[2]<<8)|b[3]); }\n\nstatic IPAddress Increment(IPAddress a){ var u=ToUint(a)+1u; return new IPAddress(new byte[]{(byte)(u>>24),(byte)(u>>16),(byte)(u>>8),(byte)u}); }\n\nuint network = ToUint(start) & ToUint(mask);\nif (network == ToUint(start)) startingAddress = Increment(start); // bump off network","typeGuard":"static bool StartIsNotNetworkAddress(IPAddress start, IPAddress mask)\n    => (ToUint(start) & ToUint(mask)) != ToUint(start);","tryCatchPattern":"try { scope.ChangeNetwork(start, end, mask); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"network address\"))\n{ start = Increment(start); scope.ChangeNetwork(start, end, mask); }","preventionTips":["Derive start as network+1 and end as broadcast-1 from the CIDR.","Reject masks with zero host bits before building a pool.","Add a config sanity check that start != network in your validation pipeline."],"tags":["dhcp","ipv4","validation","scope","subnet"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}