on 17-Mar-2015 13:02
Problem this snippet solves:
This iRule scans domain name in the query section of the DNS message. If it founds character that has value higher than 127 (according to ASCII, printable english character are number 127 or lower), it selects pool of DNS server that supports chinese name resolution. otherwise, send to pool of DNS server that only supports english. This iRule skip DNS header and start checking each character in the QNAME one-by-one. (see RFC1035 for detail of DNS protocol format) This iRule can be applied to any other language that uses value higher than 127.
Code :
when CLIENT_DATA { binary scan [UDP::payload] @3c sflags set rcode [expr $sflags & 0xf] if { $rcode == 0} { # skip the DNS header, jump to the QNAME part of first QUESTION # byte contains the first part length binary scan [UDP::payload] @12c byte # make the byte an unsigned integer set byte [expr ($byte + 0x100)%0x100] # initialize our posisition in the QNAME parsing and the text QNAME set offset 12 set i 12 ############# /extract QNAME from QUESTION header ############# while {$byte > 0 && $offset < [UDP::payload length]} { # grab a part and put it in our text QNAME section set offset [expr $offset + $byte + 1] #check each charactor one by one, see if it's bigger than 127 incr i while {$i < $offset} { binary scan [UDP::payload] @${i}c char #log local0. "debug: char=$char" if { $char < 0 } { #log "send to Chinses dns Pool" pool dns_chinese_pool #if one char is bigger than 127 (signed char mean negative), then end the rule execution return } incr i } # grab the length of the next part, and make it an unsigned integer binary scan [UDP::payload] @${offset}c byte # make the byte an unsigned integer set byte [expr ($byte + 0x100)%0x100] } #log "send to Chinses dns Pool" pool dns_english_pool } }