TCP:sockopt(t)
The TCP:sockopt() function allows you to set or retrieve various socket, IP, and TCP options, such as buffer size, timeout, and Maximum Segment Size (MSS).
Note: In FortiADC version 7.4.3, the TCP:sockopt() functionality has been extended with the added new "type" parameter that allows FortiADC to read the customized TCP option. However, the "type" parameter currently only supports the GET operations.
Syntax
TCP:sockopt(t)
Arguments
| Name | Description |
|---|---|
|
t |
A Lua table specifying the operation and option. |
The options and required parameters for the Lua table (t) depend on whether you are accessing Standard Options (using "message") or the Custom TCP Option (using "type").
1: Standard Options (Using "message")
|
Parameter Key |
Operation |
Required Value |
Example | Notes |
|---|---|---|---|---|
|
op |
"get" or "set" |
"get" or "set" |
"set" |
Specifies the action. |
|
message |
Both GET/SET |
Option Name |
"maxseg" |
"snd_buf" "rcv_buf" "so_type" "so_priority" "ip_ttl" "fastopen" "maxseg" "so_mark" "tos" "ip_mtu" "tcp_nodelay" "tcp_cork" "tcp_quickack" "keepalive" "ip_reputation" "ipv6_v6only" "linger" "snd_timeo" "rcv_timeo" |
|
value |
Only SET |
New Option Value |
1240 |
Required only for the "set" operation. |
2: Custom TCP Option (Using "type")
|
Parameter Key |
Operation |
Required Value |
Example | Notes |
|---|---|---|---|---|
|
op |
Only GET |
"get" |
"get" |
Only the GET operation is supported. |
|
type |
Only GET |
Option Number |
28 |
Specifies the custom TCP option Type. Do not use "message". |
Events
Applicable in the following events:
- HTTP_DATA_REQUEST
- HTTP_DATA_RESPONSE
- HTTP_REQUEST
- HTTP_RESPONSE
- SERVER_BEFORE_CONNECT
- SERVER_CONNECTED
- TCP_ACCEPTED
- VS_LISTENER_BIND
Examples
The following examples and notes only apply to the "type" parameter that was introduced in V7.4.3:
when HTTP_REQUEST {
debug("============begin scripting.\n")
clientip = nil
t = {}
t["op"] = "get"
-- Set the custom TCP option type
t["type"] = 28
ret = TCP:sockopt(t)
if ret and (string.len(ret)>=4) then
debug("------> TCP get sockopt(%d): (returned %d bytes) successfully.\n", t["type"], string.len(ret));
print_byte_array(ret)
clientip = binStrToIpAddress(ret)
debug("clientip = %s\n", clientip)
else
debug("------> TCP get sockopt(%d) failed.\n", t["type"])
end
if clientip then
res = HTTP:header_insert("X-Forwarded-For", clientip)
if res then
debug("------> Header inserted successfully.\n")
else
debug("------> Header failed to insert.\n")
end
end
debug("============end scripting.\n")
}
function binStrToIpAddress(binStr)
return tostring(string.byte(binStr,1)) .. "." .. tostring(string.byte(binStr,2)) ..
"." .. tostring(string.byte(binStr,3)) .. "." .. tostring(string.byte(binStr,4))
end
function print_byte_array(s)
for i=1, string.len(s) do
debug("0x%x.", string.byte(s,i))
end
debug("\n")
end
Notes:
For TCP options including Kind 28 type packet, only the first 4 bytes will be read.
For example:
Sent:
Kind: 28 Length: … 192,168,1,100,192.168,1,200,192,168,1,2
FortiADC reads:
=========begin scripting. clientip = 192.168.1.100
When the data sent is "abcd..." instead of regular numbers, decimals (ASCII code) 97,98,99,100 will be displayed.
For example:
Sent:
Kind: 28 Length: … abcdef…
FortiADC reads:
------> TCP get sockopt(28): (returned 4 bytes) successfully. 0x61.0x62.0x63.0x64. clientip = 97.98.99.100
If TCP options only contain two packets with Kind 28, only the first one will be read.
For example:
Sent:
Kind: 28 Length: 6 192,168,1,100 Kind: 28 Length: 6 192,168,1,100
FortiADC reads:
=========begin scripting. clientip = 192.168.1.100
The following examples apply to the TCP:sockopt() as introduced in V5.0:
when RULE_INIT {
debug(" ======== RULE_INIT ========\n");
-- access to https://notes.shichao.io/unp/ch7/ for more details.
tcp_message = {};
tcp_message[1]="snd_buf"; --int
tcp_message[2]="rcv_buf"; --int
setIntMsg = {};
setIntMsg[1]="snd_buf"; --int
setIntMsg[2]="rcv_buf"; --int
setIntValue = {};
setIntValue[1] = 111222;
setIntValue[2] = 111222;
}when VS_LISTENER_BIND {
--when a VS tries to bind.
debug(" ======== VS_LISTENER_BIND ========\n");
for k, v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
debug(" ==== set ==== \n");
for k, v in pairs(setIntMsg) do
s = {};
s["op"] = "set"; --or "set"
s["message"] = v
s["value"] = setIntValue[k]; -- for integer value
result = TCP:sockopt(s);
debug("setting %s to %s return %s\n",v,setIntValue[k], result);
end
debug(" ==== End set ==== \n");
for k, v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
}
when HTTP_RESPONSE {
debug(" ======== HTTP_RESPONSE ========\n");
t={}
t["size"] = 100;
HTTP:collect(t)
debug(" ==== set ==== \n");
for k, v in pairs(setIntMsg) do
s = {};
s["op"] = "set"; --or "set"
s["message"] = v
s["value"] = setIntValue[k]; -- for integer value
result = TCP:sockopt(s);
debug("setting %s to %s return %s\n",v,setIntValue[k], result);
end
debug(" ==== End set ==== \n");
for k, v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
}when HTTP_DATA_RESPONSE {
debug(" ======== HTTP_DATA_RESPONSE ========\n");
debug(" ==== set ==== \n");
for k, v in pairs(setIntMsg) do
s = {};
s["op"] = "set"; --or "set"
s["message"] = v
s["value"] = setIntValue[k]; -- for integer value
result = TCP:sockopt(s);
debug("setting %s to %s return %s\n",v,setIntValue[k], result);
end
debug(" ==== End set ==== \n");
for k, v in pairs(tcp_message) do
t = {};
t["op"] = "get"
t["message"]=v
if TCP:sockopt(t) then
debug("%s value is %d\n",v, TCP:sockopt(t));
else
debug("get %s status %s\n",v,TCP:sockopt(t));
end
end
}
Supported Version
FortiADC version 5.0.x and later. Updated in version 7.4.3.