The following rule is for sending Ldap Write and Ldap Read request to different pools:
-----------------------------------------------------------------
when RULE_INIT {
# Read Pool
set static::readPool LdapTestRead
# Write Pool
set static::writePool LdapTestWrite
# Turn on debugging
set static::ldap_debug 0
# A lookup table for debugging
array set static::msg_types {
0 "bind request"
1 "bind response"
2 "unbind request"
3 "search request"
4 "search response"
6 "modify request"
7 "modify response"
8 "add request"
9 "add response"
10 "delete request"
11 "delete response"
12 "modifydn request"
13 "modifydn response"
14 "compare request"
15 "compare response"
16 "abandon request"
23 "extended request"
24 "extended response"
}
}
when CLIENT_ACCEPTED {
set rebind 0
set binding ""
set replayop ""
set writing 0
TCP::collect
}
when CLIENT_DATA {
# Grab the current payload collected
set payload [TCP::payload]
# Pull the first 2 bytes.
binary scan $payload H2c ber_t ber_len
# The first byte is the tag signifying an LDAP message,
# Always is hex 30, if that is not so reject
if { $ber_t ne "30" } {
reject
return
}
# The second byte is one of two values:
# a) The length of the packet minus the above
# defining byte and the length byte
# OR
# b) an octet describing how many subsequent bytes
# hold the packet length
# In either case the message type (what we are after)
# follows the message id field which too can be a variable
# number of bytes.
set len_bytes 0
if { [expr [expr ($ber_len + 0x100) % 0x100] & 128] > 0 } {
set len_bytes [expr [expr ($ber_len + 0x100) % 0x100] & 127]
}
# How many bytes is the message id
binary scan $payload x[expr 3 + $len_bytes]c msgid_bytes
# The message type is then 4 bytes + number length bytes + number of
# message id bytes offset.
binary scan $payload x[expr 4 + $len_bytes + $msgid_bytes]c msgtype
# msgtype - BER encoded value, bits 1-5 are the actual
# type, 6 is the data type, 7-8 are the data class
# Here we only care about the lower 5 bits
set msgtype [expr $msgtype & 31]
if {$static::ldap_debug and
[catch {
log local0. "message type is: $static::msg_types($msgtype) $msgtype"
}
]
} {
log local0. "Bad message type: $msgtype"
reject
}
# Each connection should start with a bind request
# We'll save this packet for later rebinding when we
# flip between servers
if { $msgtype == 0 } {
if {$static::ldap_debug} {log local0. "Bind Request with: ldap_read"}
set writing 0
set rebind 0
set binding $payload
LB::detach
pool $static::readPool
# If we come across a write request and are currently not
# sending data to the write pool, detach, and set the rebind
# flag so we can send the bind packet before we actually send
# our write request
} elseif {(( $msgtype == 6 ) or ( $msgtype == 8 ) or ( $msgtype == 10 ) or ( $msgtype == 12 )) and $writing != 1} {
if {$static::ldap_debug} {log local0. "Rebinding with: ldap_write"}
set rebind 1
set writing 1
set replayop $payload
TCP::payload replace 0 [TCP::payload length] $binding
LB::detach
pool $static::writePool
# If we come across a read request while we are bound to a write server
# we need to detach and rebind with a read server from the read pool
} elseif {(( $msgtype == 6 ) or ( $msgtype == 8 ) or ( $msgtype == 10 ) or ( $msgtype == 12 )) and $writing == 1} {
if {$static::ldap_debug} {log local0. "Rebinding with: ldap_read"}
set rebind 1
set writing 0
set replayop $payload
TCP::payload replace 0 [TCP::payload length] $binding
LB::detach
pool $static::readPool
}
TCP::release
TCP::collect
}
when SERVER_CONNECTED {
# A change in the type of request has been detected
# requiring a rebind, we've sent the bind now we need to
# wait for the response before we send the actual request
if { $rebind == 1 } {
TCP::collect
}
}
when SERVER_DATA {
if { $rebind == 1 } {
set rebind 0
# See above for details on this block. Stupid iRules, no proc grrrr
set payload [TCP::payload]
# Pull the first 2 bytes.
binary scan $payload H2c ber_t ber_len
set len_bytes 0
if { [expr [expr ($ber_len + 0x100) % 0x100] & 128] > 0 } {
set len_bytes [expr [expr ($ber_len + 0x100) % 0x100] & 127]
}
binary scan $payload x[expr 3 + $len_bytes]c msgid_bytes
binary scan $payload x[expr 4 + $len_bytes + $msgid_bytes]c msgtype
set msgtype [expr $msgtype & 31]
# If the msgtype we have here is for a bind response just discard
# it as we don't need to send it to the client
if {$msgtype == 1 } {
TCP::payload replace 0 [TCP::payload length] ""
}
# Now send the actual read or write op to the server
# It should now have processed the bind
TCP::respond $replayop
}
TCP::release
}
---------------------------------------------------------------
No comments:
Post a Comment