Unfortunately not. I'll start by providing an iRule that will work, then provide some commentary.
I assume that you want to match on individual IP addresses, rather than all IP addresses in netblocks. That is, a query from 10.10.10.5 should go to pool1, but it is not necessarily the case that all IPs in 10.10.10.0/24 should. If that is so, this iRule achieves that:
when DNS_REQUEST {
switch [IP::client_addr] {
"10.10.10.5" {
pool pool1
}
"10.10.20.5" {
pool pool2
}
"10.10.30.5" {
pool pool3
}
}
}
Generally speaking, a when clause for a specific event (DNS_REQUEST in this example) occurs only once in a particular iRule. As with most general purpose programming languages, iRules (a Tcl dialect) supports conditionals (both if/elseif/else and switch, as above), which is where the decision making happens.
iRule commands broadly come in two forms: inquisitive and imperative. An inquisitive command returns a value, while an imperative command instructs the system to do something. Inquisitive commands should always be wrapped in the square brackets ([]), while imperative commands usually are not. In Tcl, the square brackets force inline evaluation of the statement contained within the brackets. Inquisitive commands are expected to evaluate to a value which you subsequently use (e.g., as the conditional for the switch above); thus, the reason why square brackets are needed. Notice that the pool command -- which is imperative -- is not wrapped in square brackets. We don't expect it to evaluate to a value, and even if it did, we don't need the return value.
I mention this because there is a form of IP::addr which can be used for netblock comparison, as in:
if { [IP::addr [IP::client_addr] equals "10.10.10.0/24"] } { pool1 }
Notice that both IP::client_addr and IP::addr are wrapped in square brackets. We want them both to evaluate to something (an IP address and a boolean, respectively).
For completeness, you can use a slight variant of the IP::addr statements you have above in an if conditional:
when DNS_REQUEST {
if { [IP::addr [IP::client_addr] equals "10.10.10.5"] } {
pool pool1
}
elseif { [IP::addr [IP::client_addr] equals "10.10.20.5"] } {
pool pool2
}
elseif { [IP::addr [IP::client_addr] equals "10.10.30.5"] } {
pool pool3
}
}
but I consider that to be less readable. And, strictly speaking, the IP::addr is not needed. The following would suffice:
when DNS_REQUEST {
if { [IP::client_addr] equals "10.10.10.5" } {
pool pool1
}
... etc ...
}
Since, in this context, IP::client_addr produces a string.
A few things to keep in mind:
- Usually, with this type of rule, it's a good idea to have a default pool defined. You could do this via the iRule, or better yet, attach a pool to the virtual server on which this iRule is defined;
- This will only work on the LTM module if GTM is licensed as well, or with a DNS Services add-on license. If neither of those are true, the DNS_REQUEST event is not defined and will never fire.