void tcpv4_add_listener(struct listener *listener);
void tcpv6_add_listener(struct listener *listener);
int tcp_connect_server(struct stream_interface *si);
+int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
+int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit);
int tcp_inspect_response(struct session *s, struct buffer *rep, int an_bit);
int tcp_exec_req_rules(struct session *s);
#include <types/task.h>
void uxst_add_listener(struct listener *listener);
+int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
+int uxst_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
#endif /* _PROTO_PROTO_UXST_H */
#endif
}
-
-/*
- * Retrieves the original destination address for the stream interface. On the
- * client side, if the original destination address was translated, the original
- * address is retrieved.
- */
-static inline void stream_sock_get_to_addr(struct stream_interface *si)
-{
- socklen_t namelen;
-
- if (si->flags & SI_FL_TO_SET)
- return;
-
- namelen = sizeof(si->addr.to);
-
-#if defined(TPROXY) && defined(SO_ORIGINAL_DST)
- if (getsockopt(si->fd, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr *)&si->addr.to, &namelen) != -1) {
- si->flags |= SI_FL_TO_SET;
- return;
- }
-#endif
- if (si->proto->get_dst &&
- si->proto->get_dst(si->fd, (struct sockaddr *)&si->addr.to, &namelen) != -1)
- si->flags |= SI_FL_TO_SET;
- return;
-}
-
-/*
- * Retrieves the source address for the stream interface.
- */
-static inline void stream_sock_get_from_addr(struct stream_interface *si)
-{
- socklen_t namelen;
-
- if (si->flags & SI_FL_FROM_SET)
- return;
-
- namelen = sizeof(si->addr.to);
- if (si->proto->get_src &&
- si->proto->get_src(si->fd, (struct sockaddr *)&si->addr.from, &namelen) != -1)
- si->flags |= SI_FL_FROM_SET;
- return;
-}
-
-
#endif /* _PROTO_STREAM_SOCK_H */
/*
memcpy(&si->sock, ops, sizeof(si->sock));
}
+
+/* Retrieves the source address for the stream interface. */
+static inline void si_get_from_addr(struct stream_interface *si)
+{
+ if (si->flags & SI_FL_FROM_SET)
+ return;
+
+ if (!si->proto || !si->proto->get_src)
+ return;
+
+ if (si->proto->get_src(si->fd, (struct sockaddr *)&si->addr.from,
+ sizeof(si->addr.from),
+ si->target.type != TARG_TYPE_CLIENT) == -1)
+ return;
+ si->flags |= SI_FL_FROM_SET;
+}
+
+/* Retrieves the original destination address for the stream interface. */
+static inline void si_get_to_addr(struct stream_interface *si)
+{
+ if (si->flags & SI_FL_TO_SET)
+ return;
+
+ if (!si->proto || !si->proto->get_dst)
+ return;
+
+ if (si->proto->get_dst(si->fd, (struct sockaddr *)&si->addr.to,
+ sizeof(si->addr.to),
+ si->target.type != TARG_TYPE_CLIENT) == -1)
+ return;
+ si->flags |= SI_FL_TO_SET;
+}
+
+
#endif /* _PROTO_STREAM_INTERFACE_H */
/*
int (*enable_all)(struct protocol *proto); /* enable all bound listeners */
int (*disable_all)(struct protocol *proto); /* disable all bound listeners */
int (*connect)(struct stream_interface *); /* connect function if any */
- int (*get_src)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve src addr */
- int (*get_dst)(int, struct sockaddr *, socklen_t *); /* syscall used to retrieve dst addr */
+ int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve src addr */
+ int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve dst addr */
struct list listeners; /* list of listeners using this protocol */
int nb_listeners; /* number of listeners */
* locally on multiple addresses at once.
*/
if (!(s->be->options & PR_O_TRANSP))
- stream_sock_get_to_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
if (s->req->prod->addr.to.ss_family == AF_INET) {
((struct sockaddr_in *)&s->req->cons->addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->addr.to)->sin_addr;
int base_port;
if (!(s->be->options & PR_O_TRANSP))
- stream_sock_get_to_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
/* First, retrieve the port from the incoming connection */
base_port = get_host_port(&s->req->prod->addr.to);
}
else if (s->be->options & PR_O_TRANSP) {
/* in transparent mode, use the original dest addr if no dispatch specified */
- stream_sock_get_to_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
if (s->req->prod->addr.to.ss_family == AF_INET || s->req->prod->addr.to.ss_family == AF_INET6) {
memcpy(&s->req->cons->addr.to, &s->req->prod->addr.to, MIN(sizeof(s->req->cons->addr.to), sizeof(s->req->prod->addr.to)));
s->req->cons->send_proxy_ofs = 0;
if (s->target.type == TARG_TYPE_SERVER && (s->target.ptr.s->state & SRV_SEND_PROXY)) {
s->req->cons->send_proxy_ofs = 1; /* must compute size */
- stream_sock_get_to_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
}
/* set the correct protocol on the output stream interface */
sess->listener ? sess->listener->name ? sess->listener->name : "?" : "?",
sess->listener ? sess->listener->luid : 0);
- stream_sock_get_to_addr(&sess->si[0]);
+ si_get_to_addr(&sess->si[0]);
switch (addr_to_str(&sess->si[0].addr.to, pn, sizeof(pn))) {
case AF_INET:
case AF_INET6:
else
chunk_printf(&msg, " backend=<NONE> (id=-1 mode=-)");
- stream_sock_get_from_addr(&sess->si[1]);
+ si_get_from_addr(&sess->si[1]);
switch (addr_to_str(&sess->si[1].addr.from, pn, sizeof(pn))) {
case AF_INET:
case AF_INET6:
else
chunk_printf(&msg, " server=<NONE> (id=-1)");
- stream_sock_get_to_addr(&sess->si[1]);
+ si_get_to_addr(&sess->si[1]);
switch (addr_to_str(&sess->si[1].addr.to, pn, sizeof(pn))) {
case AF_INET:
case AF_INET6:
else {
char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
- stream_sock_get_from_addr(s->req->prod);
- stream_sock_get_to_addr(s->req->prod);
+ si_get_from_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) {
case AF_INET:
char pn[INET6_ADDRSTRLEN];
int len = 0;
- stream_sock_get_from_addr(s->req->prod);
+ si_get_from_addr(s->req->prod);
switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) {
case AF_INET:
break;
case LOG_FMT_FRONTENDIP: // %Fi
- stream_sock_get_to_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->addr.to,
dst + maxsize - tmplog, tmp);
if (ret == NULL)
break;
case LOG_FMT_FRONTENDPORT: // %Fp
- stream_sock_get_to_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
if (s->req->prod->addr.to.ss_family == AF_UNIX) {
ret = ltoa_o(s->listener->luid,
tmplog, dst + maxsize - tmplog);
/* Add an X-Original-To header unless the destination IP is
* in the 'except' network range.
*/
- stream_sock_get_to_addr(s->req->prod);
+ si_get_to_addr(s->req->prod);
if (s->req->prod->addr.to.ss_family == AF_INET &&
((!s->fe->except_mask_to.s_addr ||
#include <proto/session.h>
#include <proto/sock_raw.h>
#include <proto/stick_table.h>
+#include <proto/stream_interface.h>
#include <proto/task.h>
#include <proto/buffers.h>
.bind_all = tcp_bind_listeners,
.unbind_all = unbind_all_listeners,
.enable_all = enable_all_listeners,
+ .get_src = tcp_get_src,
+ .get_dst = tcp_get_dst,
.listeners = LIST_HEAD_INIT(proto_tcpv4.listeners),
.nb_listeners = 0,
};
.bind_all = tcp_bind_listeners,
.unbind_all = unbind_all_listeners,
.enable_all = enable_all_listeners,
+ .get_src = tcp_get_src,
+ .get_dst = tcp_get_dst,
.listeners = LIST_HEAD_INIT(proto_tcpv6.listeners),
.nb_listeners = 0,
};
/* needs src ip/port for logging */
if (si->flags & SI_FL_SRC_ADDR)
- stream_sock_get_from_addr(si);
+ si_get_from_addr(si);
fdtab[fd].owner = si;
fdtab[fd].state = FD_STCONN; /* connection in progress */
}
+/*
+ * Retrieves the source address for the socket <fd>, with <dir> indicating
+ * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of
+ * success, -1 in case of error. The socket's source address is stored in
+ * <sa> for <salen> bytes.
+ */
+int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+ if (dir)
+ return getsockname(fd, sa, &salen);
+ else
+ return getpeername(fd, sa, &salen);
+}
+
+
+/*
+ * Retrieves the original destination address for the socket <fd>, with <dir>
+ * indicating if we're a listener (=0) or an initiator (!=0). In the case of a
+ * listener, if the original destination address was translated, the original
+ * address is retrieved. It returns 0 in case of success, -1 in case of error.
+ * The socket's source address is stored in <sa> for <salen> bytes.
+ */
+int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+ if (dir)
+ return getpeername(fd, sa, &salen);
+#if defined(TPROXY) && defined(SO_ORIGINAL_DST)
+ else if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
+ return 0;
+#endif
+ else
+ return getsockname(fd, sa, &salen);
+}
+
+
/* This function tries to bind a TCPv4/v6 listener. It may return a warning or
* an error message in <err> if the message is at most <errlen> bytes long
* (including '\0'). The return value is composed from ERR_ABORT, ERR_WARN,
smp_fetch_dst(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
- stream_sock_get_to_addr(&l4->si[0]);
+ si_get_to_addr(&l4->si[0]);
switch (l4->si[0].addr.to.ss_family) {
case AF_INET:
smp_fetch_dport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
- stream_sock_get_to_addr(&l4->si[0]);
+ si_get_to_addr(&l4->si[0]);
smp->type = SMP_T_UINT;
if (!(smp->data.uint = get_host_port(&l4->si[0].addr.to)))
.unbind_all = uxst_unbind_listeners,
.enable_all = enable_all_listeners,
.disable_all = disable_all_listeners,
+ .get_src = uxst_get_src,
+ .get_dst = uxst_get_dst,
.listeners = LIST_HEAD_INIT(proto_unix.listeners),
.nb_listeners = 0,
};
* 1) low-level socket functions
********************************/
+/*
+ * Retrieves the source address for the socket <fd>, with <dir> indicating
+ * if we're a listener (=0) or an initiator (!=0). It returns 0 in case of
+ * success, -1 in case of error. The socket's source address is stored in
+ * <sa> for <salen> bytes.
+ */
+int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+ if (dir)
+ return getsockname(fd, sa, &salen);
+ else
+ return getpeername(fd, sa, &salen);
+}
+
+
+/*
+ * Retrieves the original destination address for the socket <fd>, with <dir>
+ * indicating if we're a listener (=0) or an initiator (!=0). It returns 0 in
+ * case of success, -1 in case of error. The socket's source address is stored
+ * in <sa> for <salen> bytes.
+ */
+int uxst_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
+{
+ if (dir)
+ return getpeername(fd, sa, &salen);
+ else
+ return getsockname(fd, sa, &salen);
+}
+
/* Tries to destroy the UNIX stream socket <path>. The socket must not be used
* anymore. It practises best effort, and no error is returned.