| 2013/10/10 - possibilities for setting source and destination addresses |
| |
| |
| When establishing a connection to a remote device, this device is designated |
| as a target, which designates an entity defined in the configuration. A same |
| target appears only once in a configuration, and multiple targets may share |
| the same settings if needed. |
| |
| The following types of targets are currently supported : |
| |
| - listener : all connections with this type of target come from clients ; |
| - server : connections to such targets are for "server" lines ; |
| - peer : connections to such target address "peer" lines in "peers" |
| sections ; |
| - proxy : these targets are used by "dispatch", "option transparent" |
| or "option http_proxy" statements. |
| |
| A connection might not be reused between two different targets, even if all |
| parameters seem similar. One of the reason is that some parameters are specific |
| to the target and are not easy or not cheap to compare (eg: bind to interface, |
| mss, ...). |
| |
| A number of source and destination addresses may be set for a given target. |
| |
| - listener : |
| - the "from" address:port is set by accept() |
| |
| - the "to" address:port is set if conn_get_to_addr() is called |
| |
| - peer : |
| - the "from" address:port is not set |
| |
| - the "to" address:port is static and dependent only on the peer |
| |
| - server : |
| - the "from" address may be set alone when "source" is used with |
| a forced IP address, or when "usesrc clientip" is used. |
| |
| - the "from" port may be set only combined with the address when |
| "source" is used with IP:port, IP:port-range or "usesrc client" is |
| used. Note that in this case, both the address and the port may be |
| 0, meaning that the kernel will pick the address or port and that |
| the final value might not match the one explicitly set (eg: |
| important for logging). |
| |
| - the "from" address may be forced from a header which implies it |
| may change between two consecutive requests on the same connection. |
| |
| - the "to" address and port are set together when connecting to a |
| regular server, or by copying the client's IP address when |
| "server 0.0.0.0" is used. Note that the destination port may be |
| an offset applied to the original destination port. |
| |
| - proxy : |
| - the "from" address may be set alone when "source" is used with a |
| forced IP address or when "usesrc clientip" is used. |
| |
| - the "from" port may be set only combined with the address when |
| "source" is used with IP:port or with "usesrc client". There is |
| no ip:port range for a proxy as of now. Same comment applies as |
| above when port and/or address are 0. |
| |
| - the "from" address may be forced from a header which implies it |
| may change between two consecutive requests on the same connection. |
| |
| - the "to" address and port are set together, either by configuration |
| when "dispatch" is used, or dynamically when "transparent" is used |
| (1:1 with client connection) or "option http_proxy" is used, where |
| each client request may lead to a different destination address. |
| |
| |
| At the moment, there are some limits in what might happen between multiple |
| concurrent requests to a same target. |
| |
| - peers parameter do not change, so no problem. |
| |
| - server parameters may change in this way : |
| - a connection may require a source bound to an IP address found in a |
| header, which will fall back to the "source" settings if the address |
| is not found in this header. This means that the source address may |
| switch between a dynamically forced IP address and another forced |
| IP and/or port range. |
| |
| - if the element is not found (eg: header), the remaining "forced" |
| source address might very well be empty (unset), so the connection |
| reuse is acceptable when switching in that direction. |
| |
| - it is not possible to switch between client and clientip or any of |
| these and hdr_ip() because they're exclusive. |
| |
| - using a source address/port belonging to a port range is compatible |
| with connection reuse because there is a single range per target, so |
| switching from a range to another range means we remain in the same |
| range. |
| |
| - destination address may currently not change since the only possible |
| case for dynamic destination address setting is the transparent mode, |
| reproducing the client's destination address. |
| |
| - proxy parameters may change in this way : |
| - a connection may require a source bound to an IP address found in a |
| header, which will fall back to the "source" settings if the address |
| is not found in this header. This means that the source address may |
| switch between a dynamically forced IP address and another forced |
| IP and/or port range. |
| |
| - if the element is not found (eg: header), the remaining "forced" |
| source address might very well be empty (unset), so the connection |
| reuse is acceptable when switching in that direction. |
| |
| - it is not possible to switch between client and clientip or any of |
| these and hdr_ip() because they're exclusive. |
| |
| - proxies do not support port ranges at the moment. |
| |
| - destination address might change in the case where "option http_proxy" |
| is used. |
| |
| So, for each source element (IP, port), we want to know : |
| - if the element was assigned by static configuration (eg: ":80") |
| - if the element was assigned from a connection-specific value (eg: usesrc clientip) |
| - if the element was assigned from a configuration-specific range (eg: 1024-65535) |
| - if the element was assigned from a request-specific value (eg: hdr_ip(xff)) |
| - if the element was not assigned at all |
| |
| For the destination, we want to know : |
| - if the element was assigned by static configuration (eg: ":80") |
| - if the element was assigned from a connection-specific value (eg: transparent) |
| - if the element was assigned from a request-specific value (eg: http_proxy) |
| |
| We don't need to store the information about the origin of the dynamic value |
| since we have the value itself. So in practice we have : |
| - default value, unknown (not yet checked with getsockname/getpeername) |
| - default value, known (check done) |
| - forced value (known) |
| - forced range (known) |
| |
| We can't do that on an ip:port basis because the port may be fixed regardless |
| of the address and conversely. |
| |
| So that means : |
| |
| enum { |
| CO_ADDR_NONE = 0, /* not set, unknown value */ |
| CO_ADDR_KNOWN = 1, /* not set, known value */ |
| CO_ADDR_FIXED = 2, /* fixed value, known */ |
| CO_ADDR_RANGE = 3, /* from assigned range, known */ |
| } conn_addr_values; |
| |
| unsigned int new_l3_src_status:2; |
| unsigned int new_l4_src_status:2; |
| unsigned int new_l3_dst_status:2; |
| unsigned int new_l4_dst_status:2; |
| |
| unsigned int cur_l3_src_status:2; |
| unsigned int cur_l4_src_status:2; |
| unsigned int cur_l3_dsp_status:2; |
| unsigned int cur_l4_dst_status:2; |
| |
| unsigned int new_family:2; |
| unsigned int cur_family:2; |
| |
| Note: this obsoletes CO_FL_ADDR_FROM_SET and CO_FL_ADDR_TO_SET. These flags |
| must be changed to individual l3+l4 checks ORed between old and new values, |
| or better, set to cur only which will inherit new. |
| |
| In the connection, these values may be merged in the same word as err_code. |