This question evaluates understanding of IPv4 addressing and CIDR prefix matching, including bitwise reasoning, robust parsing, handling of edge cases, and algorithmic efficiency for large rule sets.
Implement a simple IPv4 firewall rule matcher.
You are given an ordered list of firewall rules. Each rule has:
ALLOW
or
DENY
A.B.C.D/L
, where:
A, B, C, D
are integers in
[0, 255]
L
(the prefix length) is an integer in
[0, 32]
The firewall processes incoming IPv4 addresses in order of the rules:
L
bits of the IP are equal to the first
L
bits of the rule's network address.
DENY
.
Design and implement a function:
bool isAllowed(List<Rule> rules, string ipAddress)
where:
rules
is the ordered list of rules, each with
action
∈ {
"ALLOW"
,
"DENY"
} and
cidr
∈ IPv4 CIDR format
"A.B.C.D/L"
.
ipAddress
is a string in IPv4 dotted format
"A.B.C.D"
.
The function should return true if the IP is allowed by the rule set, and false otherwise.
You should:
/0
(matches all IPs) and
/32
(matches exactly one IP).
10^5
rules and
10^5
queries, and aim for an efficient solution.
List and explain a set of important test cases you would use to validate your implementation, including:
Extend the API so that the input to check is itself a CIDR block, e.g. "10.0.1.0/24", instead of a single IP.
Define and implement a function with a suitable signature, for example:
Result checkRange(List<Rule> rules, string cidrRange)
Decide and justify the semantics of Result, for example:
Clearly specify the matching and precedence rules when a CIDR range query overlaps multiple firewall rules.
Formally specify, in terms of 32‑bit integers and bit operations, the exact condition under which an IPv4 address matches a CIDR network/prefixLength pair.