diff --git a/include/haproxy/session-t.h b/include/haproxy/session-t.h index 45b820cb3..1afb3c857 100644 --- a/include/haproxy/session-t.h +++ b/include/haproxy/session-t.h @@ -39,6 +39,8 @@ enum { SESS_FL_NONE = 0x00000000, /* nothing */ SESS_FL_PREFER_LAST = 0x00000001, /* NTML authent, we should reuse last conn */ + SESS_FL_ADDR_FROM_SET = 0x00000002, + SESS_FL_ADDR_TO_SET = 0x00000004, }; /* max number of idle server connections kept attached to a session */ @@ -58,6 +60,8 @@ struct session { int idle_conns; /* Number of connections we're currently responsible for that we are not using */ unsigned int flags; /* session flags, SESS_FL_* */ struct list srv_list; /* List of servers and the connections the session is currently responsible for */ + struct sockaddr_storage *src; /* source address (pool), when known, otherwise NULL */ + struct sockaddr_storage *dst; /* destination address (pool), when known, otherwise NULL */ }; struct sess_srv_list { diff --git a/include/haproxy/session.h b/include/haproxy/session.h index d838fd99b..f4abcc333 100644 --- a/include/haproxy/session.h +++ b/include/haproxy/session.h @@ -23,6 +23,7 @@ #define _HAPROXY_SESSION_H #include +#include #include #include #include @@ -232,6 +233,88 @@ static inline struct connection *session_get_conn(struct session *sess, void *ta return srv_conn; } +/* Returns the source address of the session and fallbacks on the client + * connection if not set. It returns a const address on succes or NULL on + * failure. + */ +static inline const struct sockaddr_storage *sess_src(struct session *sess) +{ + struct connection *cli_conn = objt_conn(sess->origin); + + if (sess->flags & SESS_FL_ADDR_FROM_SET) + return sess->src; + if (cli_conn && conn_get_src(cli_conn)) + return conn_src(cli_conn); + return NULL; +} + +/* Returns the destination address of the session and fallbacks on the client + * connection if not set. It returns a const address on succes or NULL on + * failure. + */ +static inline const struct sockaddr_storage *sess_dst(struct session *sess) +{ + struct connection *cli_conn = objt_conn(sess->origin); + + if (sess->flags & SESS_FL_ADDR_TO_SET) + return sess->dst; + if (cli_conn && conn_get_dst(cli_conn)) + return conn_dst(cli_conn); + return NULL; +} + + +/* Retrieves the source address of the session . Returns non-zero on + * success or zero on failure. The operation is only performed once and the + * address is stored in the session for future use. On the first call, the + * session source address is copied from the client connection one. + */ +static inline int sess_get_src(struct session *sess) +{ + struct connection *cli_conn = objt_conn(sess->origin); + const struct sockaddr_storage *src = NULL; + + if (sess->flags & SESS_FL_ADDR_FROM_SET) + return 1; + + if (cli_conn && conn_get_src(cli_conn)) + src = conn_src(cli_conn); + if (!src) + return 0; + + if (!sockaddr_alloc(&sess->src, src, sizeof(*src))) + return 0; + + sess->flags |= SESS_FL_ADDR_FROM_SET; + return 1; +} + + +/* Retrieves the destination address of the session . Returns non-zero on + * success or zero on failure. The operation is only performed once and the + * address is stored in the session for future use. On the first call, the + * session destination address is copied from the client connection one. + */ +static inline int sess_get_dst(struct session *sess) +{ + struct connection *cli_conn = objt_conn(sess->origin); + const struct sockaddr_storage *dst = NULL; + + if (sess->flags & SESS_FL_ADDR_TO_SET) + return 1; + + if (cli_conn && conn_get_dst(cli_conn)) + dst = conn_dst(cli_conn); + if (!dst) + return 0; + + if (!sockaddr_alloc(&sess->dst, dst, sizeof(*dst))) + return 0; + + sess->flags |= SESS_FL_ADDR_TO_SET; + return 1; +} + #endif /* _HAPROXY_SESSION_H */ /* diff --git a/src/session.c b/src/session.c index d913d567d..06ace8a0f 100644 --- a/src/session.c +++ b/src/session.c @@ -56,6 +56,8 @@ struct session *session_new(struct proxy *fe, struct listener *li, enum obj_type LIST_INIT(&sess->srv_list); sess->idle_conns = 0; sess->flags = SESS_FL_NONE; + sess->src = NULL; + sess->dst = NULL; } return sess; } @@ -90,6 +92,8 @@ void session_free(struct session *sess) } pool_free(pool_head_sess_srv_list, srv_list); } + sockaddr_free(&sess->src); + sockaddr_free(&sess->dst); pool_free(pool_head_session, sess); _HA_ATOMIC_DEC(&jobs); }