diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index 2a44e1471..882539ebf 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -160,6 +160,7 @@ struct protocol { /* default I/O handler */ void (*default_iocb)(int fd); /* generic I/O handler (typically accept callback) */ int (*get_info)(struct connection *conn, long long int *info, int info_num); /* Callback to get connection level statistical counters */ + int (*get_opt)(const struct connection *conn, int level, int optname, void *buf, int size); /* getsockopt(level:optname) into buf:size */ uint flags; /* flags describing protocol support (PROTO_F_*) */ uint nb_receivers; /* number of receivers (under proto_lock) */ diff --git a/include/haproxy/sock.h b/include/haproxy/sock.h index 9aa014751..0642f7797 100644 --- a/include/haproxy/sock.h +++ b/include/haproxy/sock.h @@ -46,6 +46,7 @@ struct connection *sock_accept_conn(struct listener *l, int *status); void sock_accept_iocb(int fd); void sock_conn_ctrl_init(struct connection *conn); void sock_conn_ctrl_close(struct connection *conn); +int sock_conn_get_opt(const struct connection *conn, int level, int optname, void *buf, int size); void sock_conn_iocb(int fd); int sock_conn_check(struct connection *conn); int sock_drain(struct connection *conn); diff --git a/src/sock.c b/src/sock.c index bda07024e..c1e88413f 100644 --- a/src/sock.c +++ b/src/sock.c @@ -905,6 +905,23 @@ void sock_conn_ctrl_close(struct connection *conn) conn->handle.fd = DEAD_FD_MAGIC; } +/* call getsockopt() for and on connection 's socket, + * store the result in for at most bytes, and return the number + * of bytes read on success (which may be zero). Returns < 0 on error. + * Note that the recommended way to use the level is to pass IPPROTO_TCP for + * TCP_*, IPPROTO_UDP for UDP_*, IPPROTO_IP for IP_*, IPPROTO_IPV6 for IPV6_*, + * and SOL_SOCKET for UNIX sockets. + */ +int sock_conn_get_opt(const struct connection *conn, int level, int optname, void *buf, int size) +{ + socklen_t opt_len = size; + + if (getsockopt(conn->handle.fd, level, optname, buf, &opt_len) == -1) + return -1; + + return opt_len; +} + /* This is the callback which is set when a connection establishment is pending * and we have nothing to send. It may update the FD polling status to indicate * !READY. It returns 0 if it fails in a fatal way or needs to poll to go