MINOR: protocol: add get_src() and get_dst() at the protocol level

Right now the proto_fam descriptor provides a family-specific
get_src() and get_dst() pair of calls to retrieve a socket's source
or destination address. However this only works for connected mode
sockets. QUIC provides its own stream protocol, which relies on a
datagram protocol underneath, so the get_src()/get_dst() at that
protocol's family will not work, and QUIC would need to provide its
own.

This patch implements get_src() and get_dst() at the protocol level
from a connection, and makes sure that conn_get_src()/conn_get_dst()
will automatically use them if defined before falling back to the
family's pair of functions.
This commit is contained in:
Willy Tarreau 2022-04-08 13:49:17 +02:00
parent 987c08a5e2
commit e151609110
2 changed files with 15 additions and 2 deletions

View File

@ -354,6 +354,11 @@ static inline int conn_get_src(struct connection *conn)
if (!sockaddr_alloc(&conn->src, NULL, 0)) if (!sockaddr_alloc(&conn->src, NULL, 0))
goto fail; goto fail;
/* some stream protocols may provide their own get_src/dst functions */
if (conn->ctrl->get_src &&
conn->ctrl->get_src(conn, (struct sockaddr *)conn->src, sizeof(*conn->src)) != -1)
goto done;
if (conn->ctrl->proto_type != PROTO_TYPE_STREAM) if (conn->ctrl->proto_type != PROTO_TYPE_STREAM)
goto fail; goto fail;
@ -388,6 +393,11 @@ static inline int conn_get_dst(struct connection *conn)
if (!sockaddr_alloc(&conn->dst, NULL, 0)) if (!sockaddr_alloc(&conn->dst, NULL, 0))
goto fail; goto fail;
/* some stream protocols may provide their own get_src/dst functions */
if (conn->ctrl->get_dst &&
conn->ctrl->get_dst(conn, (struct sockaddr *)conn->dst, sizeof(*conn->dst)) != -1)
goto done;
if (conn->ctrl->proto_type != PROTO_TYPE_STREAM) if (conn->ctrl->proto_type != PROTO_TYPE_STREAM)
goto fail; goto fail;

View File

@ -75,8 +75,8 @@ struct proto_fam {
int l3_addrlen; /* layer3 address length, used by hashes */ int l3_addrlen; /* layer3 address length, used by hashes */
int (*addrcmp)(const struct sockaddr_storage *, const struct sockaddr_storage *); /* compare addresses (like memcmp) */ int (*addrcmp)(const struct sockaddr_storage *, const struct sockaddr_storage *); /* compare addresses (like memcmp) */
int (*bind)(struct receiver *rx, char **errmsg); /* bind a receiver */ int (*bind)(struct receiver *rx, char **errmsg); /* bind a receiver */
int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve src addr */ int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve connection's src addr */
int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve dst addr */ int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve connection's dst addr */
void (*set_port)(struct sockaddr_storage *, int port); /* set the port on the address; NULL if not implemented */ void (*set_port)(struct sockaddr_storage *, int port); /* set the port on the address; NULL if not implemented */
}; };
@ -103,6 +103,7 @@ struct protocol {
int (*suspend)(struct listener *l); /* try to suspend the listener */ int (*suspend)(struct listener *l); /* try to suspend the listener */
int (*resume)(struct listener *l); /* try to resume a suspended listener */ int (*resume)(struct listener *l); /* try to resume a suspended listener */
struct connection *(*accept_conn)(struct listener *l, int *status); /* accept a new connection */ struct connection *(*accept_conn)(struct listener *l, int *status); /* accept a new connection */
/* functions acting on connections */ /* functions acting on connections */
void (*ctrl_init)(struct connection *); /* completes initialization of the connection */ void (*ctrl_init)(struct connection *); /* completes initialization of the connection */
void (*ctrl_close)(struct connection *); /* completes release of the connection */ void (*ctrl_close)(struct connection *); /* completes release of the connection */
@ -110,6 +111,8 @@ struct protocol {
int (*drain)(struct connection *); /* drain pending data; 0=failed, >0=success */ int (*drain)(struct connection *); /* drain pending data; 0=failed, >0=success */
int (*check_events)(struct connection *conn, int event_type); /* subscribe to socket events */ int (*check_events)(struct connection *conn, int event_type); /* subscribe to socket events */
void (*ignore_events)(struct connection *conn, int event_type); /* unsubscribe from socket events */ void (*ignore_events)(struct connection *conn, int event_type); /* unsubscribe from socket events */
int (*get_src)(struct connection *conn, struct sockaddr *, socklen_t); /* retrieve connection's source address; -1=fail */
int (*get_dst)(struct connection *conn, struct sockaddr *, socklen_t); /* retrieve connection's dest address; -1=fail */
/* functions acting on the receiver */ /* functions acting on the receiver */
int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */ int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */