* CAUTION! Always update CONN_HASH_PARAMS_TYPE_COUNT when adding a new entry.
*/
enum conn_hash_params_t {
- CONN_HASH_PARAMS_TYPE_SNI = 0x1,
+ CONN_HASH_PARAMS_TYPE_SNI = 0x1,
+ CONN_HASH_PARAMS_TYPE_DST_ADDR = 0x2,
+ CONN_HASH_PARAMS_TYPE_DST_PORT = 0x4,
};
-#define CONN_HASH_PARAMS_TYPE_COUNT 1
+#define CONN_HASH_PARAMS_TYPE_COUNT 3
#define CONN_HASH_PAYLOAD_LEN \
(((sizeof(((struct connection *)0)->hash)) * 8) - CONN_HASH_PARAMS_TYPE_COUNT)
struct conn_hash_params {
struct server *srv;
XXH64_hash_t *sni_prehash;
+ struct sockaddr_storage *dst_addr;
};
/* This structure describes a connection with its methods and data.
}
#endif /* USE_OPENSSL */
+ /* 2. destination address */
+ if (!(s->flags & SF_ADDR_SET)) {
+ err = alloc_dst_address(&s->target_addr, srv, s);
+ if (err != SRV_STATUS_OK)
+ return SF_ERR_INTERNAL;
+
+ s->flags |= SF_ADDR_SET;
+ }
+
+ if (srv && (!is_addr(&srv->addr) || srv->flags & SRV_F_MAPPORTS))
+ hash_params.dst_addr = s->target_addr;
+
if (srv)
hash = conn_calculate_hash(&hash_params);
srv_conn->owner = s->sess;
if (reuse_mode == PR_O_REUSE_NEVR)
conn_set_private(srv_conn);
- }
- }
-
- if (!srv_conn || !sockaddr_alloc(&srv_conn->dst, 0, 0)) {
- if (srv_conn)
- conn_free(srv_conn);
- return SF_ERR_RESOURCE;
- }
- if (!(s->flags & SF_ADDR_SET)) {
- err = alloc_dst_address(&s->target_addr, srv, s);
- if (err != SRV_STATUS_OK) {
- conn_free(srv_conn);
- return SF_ERR_INTERNAL;
+ if (!sockaddr_alloc(&srv_conn->dst, 0, 0)) {
+ conn_free(srv_conn);
+ return SF_ERR_RESOURCE;
+ }
+ }
+ else {
+ return SF_ERR_RESOURCE;
}
-
- s->flags |= SF_ADDR_SET;
}
/* copy the target address into the connection */
INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
+/* private function to handle sockaddr as input for connection hash */
+static void conn_calculate_hash_sockaddr(const struct sockaddr_storage *ss,
+ char *buf, size_t *idx,
+ enum conn_hash_params_t *hash_flags,
+ enum conn_hash_params_t param_type_addr,
+ enum conn_hash_params_t param_type_port)
+{
+ struct sockaddr_in *addr;
+ struct sockaddr_in6 *addr6;
+
+ switch (ss->ss_family) {
+ case AF_INET:
+ addr = (struct sockaddr_in *)ss;
+
+ conn_hash_update(buf, idx,
+ &addr->sin_addr, sizeof(addr->sin_addr),
+ hash_flags, param_type_addr);
+
+ if (addr->sin_port) {
+ conn_hash_update(buf, idx,
+ &addr->sin_port, sizeof(addr->sin_port),
+ hash_flags, param_type_port);
+ }
+
+ break;
+
+ case AF_INET6:
+ addr6 = (struct sockaddr_in6 *)ss;
+
+ conn_hash_update(buf, idx,
+ &addr6->sin6_addr, sizeof(addr6->sin6_addr),
+ hash_flags, param_type_addr);
+
+ if (addr6->sin6_port) {
+ conn_hash_update(buf, idx,
+ &addr6->sin6_port, sizeof(addr6->sin6_port),
+ hash_flags, param_type_port);
+ }
+
+ break;
+ }
+}
+
XXH64_hash_t conn_calculate_hash(const struct conn_hash_params *params)
{
char *buf;
&hash_flags, CONN_HASH_PARAMS_TYPE_SNI);
}
+ if (params->dst_addr) {
+ conn_calculate_hash_sockaddr(params->dst_addr,
+ buf, &idx, &hash_flags,
+ CONN_HASH_PARAMS_TYPE_DST_ADDR,
+ CONN_HASH_PARAMS_TYPE_DST_PORT);
+ }
+
hash = conn_hash_digest(buf, idx, hash_flags);
+
return hash;
}