#include <common/config.h>
#include <types/session.h>
-void get_frt_addr(struct session *s);
int frontend_accept(struct session *s);
int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit);
int make_proxy_line(char *buf, int buf_len, struct sockaddr_storage *src, struct sockaddr_storage *dst);
}
+/*
+ * 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->get_dst &&
+ si->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->get_src &&
+ si->get_src(si->fd, (struct sockaddr *)&si->addr.from, &namelen) != -1)
+ si->flags |= SI_FL_FROM_SET;
+ return;
+}
+
+
#endif /* _PROTO_STREAM_SOCK_H */
/*
#define SN_FORCE_PRST 0x00000010 /* force persistence here, even if server is down */
#define SN_MONITOR 0x00000020 /* this session comes from a monitoring system */
#define SN_CURR_SESS 0x00000040 /* a connection is currently being counted on the server */
-#define SN_FRT_ADDR_SET 0x00000080 /* set if the frontend address has been filled */
+/* unused: 0x00000080 */
#define SN_REDISP 0x00000100 /* set if this session was redispatched from one server to another */
#define SN_CONN_TAR 0x00000200 /* set if this session is turning around before reconnecting */
#define SN_REDIRECTABLE 0x00000400 /* set if this session is redirectable (GET or HEAD) */
#define SN_IGNORE_PRST 0x00080000 /* ignore persistence */
#define SN_BE_TRACK_SC1 0x00100000 /* backend tracks stick-counter 1 */
#define SN_BE_TRACK_SC2 0x00200000 /* backend tracks stick-counter 2 */
-#define SN_BCK_ADDR_SET 0x00400000 /* set if the backend address has been filled */
/* Termination sequence tracing.
*
void (*chk_snd)(struct stream_interface *);/* chk_snd function */
int (*connect)(struct stream_interface *); /* connect function if any */
void (*release)(struct stream_interface *); /* handler to call after the last close() */
+ 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 */
/* struct members below are the "remote" part, as seen from the buffer side */
struct target target; /* the target to connect to (server, proxy, applet, ...) */
* the client asked, which is handy for remapping ports
* locally on multiple addresses at once.
*/
- if (!(s->be->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
- get_frt_addr(s);
+ if (!(s->be->options & PR_O_TRANSP))
+ stream_sock_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;
if (target_srv(&s->target)->state & SRV_MAPPORTS) {
int base_port;
- if (!(s->be->options & PR_O_TRANSP) && !(s->flags & SN_FRT_ADDR_SET))
- get_frt_addr(s);
+ if (!(s->be->options & PR_O_TRANSP))
+ stream_sock_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 */
- if (!(s->flags & SN_FRT_ADDR_SET))
- get_frt_addr(s);
+ stream_sock_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)));
*/
stream_sock_prepare_interface(s->req->cons);
s->req->cons->connect = tcp_connect_server;
+ s->req->cons->get_src = getsockname;
+ s->req->cons->get_dst = getpeername;
/* the target was only on the session, assign it to the SI now */
copy_target(&s->req->cons->target, &s->target);
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 */
- if (!(s->flags & SN_FRT_ADDR_SET))
- get_frt_addr(s);
+ stream_sock_get_to_addr(s->req->prod);
}
assign_tproxy_address(s);
#include <proto/stream_sock.h>
#include <proto/task.h>
-
-/* Retrieves the original destination address used by the client, and sets the
- * SN_FRT_ADDR_SET flag.
- */
-void get_frt_addr(struct session *s)
-{
- socklen_t namelen = sizeof(s->si[0].addr.to);
-
- if (get_original_dst(s->si[0].fd, (struct sockaddr_in *)&s->si[0].addr.to, &namelen) == -1)
- getsockname(s->si[0].fd, (struct sockaddr *)&s->si[0].addr.to, &namelen);
- s->si[0].flags |= SI_FL_TO_SET;
- s->flags |= SN_FRT_ADDR_SET;
-}
-
/* Finish a session accept() for a proxy (TCP or HTTP). It returns a negative
* value in case of a critical failure which must cause the listener to be
* disabled, a positive value in case of success, or zero if it is a success
else {
char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
- if (!(s->flags & SN_FRT_ADDR_SET))
- get_frt_addr(s);
+ stream_sock_get_from_addr(s->req->prod);
+ stream_sock_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;
- if (!(s->flags & SN_FRT_ADDR_SET))
- get_frt_addr(s);
+ stream_sock_get_from_addr(s->req->prod);
switch (addr_to_str(&s->req->prod->addr.from, pn, sizeof(pn))) {
case AF_INET:
((struct sockaddr_in *)&s->si[0].addr.to)->sin_family = AF_INET;
((struct sockaddr_in *)&s->si[0].addr.to)->sin_addr.s_addr = htonl(dst3);
((struct sockaddr_in *)&s->si[0].addr.to)->sin_port = htons(dport);
- s->flags |= SN_FRT_ADDR_SET;
-
+ s->si[0].flags |= SI_FL_FROM_SET | SI_FL_TO_SET;
}
else if (!memcmp(line, "TCP6 ", 5) != 0) {
u32 sport, dport;
((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_addr, &dst3, sizeof(struct in6_addr));
((struct sockaddr_in6 *)&s->si[0].addr.to)->sin6_port = htons(dport);
- s->flags |= SN_FRT_ADDR_SET;
+ s->si[0].flags |= SI_FL_FROM_SET | SI_FL_TO_SET;
}
else {
goto fail;
#include <proto/frontend.h>
#include <proto/log.h>
#include <proto/stream_interface.h>
+#include <proto/stream_sock.h>
const char *log_facilities[NB_LOG_FACILITIES] = {
"kern", "user", "mail", "daemon",
break;
case LOG_FMT_FRONTENDIP: // %Fi
- get_frt_addr(s);
+ stream_sock_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
- get_frt_addr(s);
+ stream_sock_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);
s->si[0].err_type = SI_ET_NONE;
s->si[0].err_loc = NULL;
s->si[0].connect = NULL;
+ s->si[0].get_src = NULL;
+ s->si[0].get_dst = NULL;
clear_target(&s->si[0].target);
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
s->si[1].err_type = SI_ET_NONE;
s->si[1].err_loc = NULL;
s->si[1].connect = tcp_connect_server;
+ s->si[1].get_src = getsockname;
+ s->si[1].get_dst = getpeername;
set_target_proxy(&s->si[1].target, s->be);
s->si[1].exp = TICK_ETERNITY;
s->si[1].flags = SI_FL_NONE;
/* Add an X-Original-To header unless the destination IP is
* in the 'except' network range.
*/
- if (!(s->flags & SN_FRT_ADDR_SET))
- get_frt_addr(s);
+ stream_sock_get_to_addr(s->req->prod);
if (s->req->prod->addr.to.ss_family == AF_INET &&
((!s->fe->except_mask_to.s_addr ||
if (global.tune.server_rcvbuf)
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf));
+ si->flags &= ~SI_FL_FROM_SET;
if ((connect(fd, (struct sockaddr *)&si->addr.to, get_addr_len(&si->addr.to)) == -1) &&
(errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
}
/* needs src ip/port for logging */
- if (si->flags & SI_FL_SRC_ADDR) {
- socklen_t addrlen = sizeof(si->addr.from);
- if (getsockname(fd, (struct sockaddr *)&si->addr.from, &addrlen) == -1) {
- Warning("Cannot get source address for logging.\n");
- }
- si->flags |= SI_FL_FROM_SET;
- }
+ if (si->flags & SI_FL_SRC_ADDR)
+ stream_sock_get_from_addr(si);
fdtab[fd].owner = si;
fdtab[fd].state = FD_STCONN; /* connection in progress */
acl_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
- if (!(l4->flags & SN_FRT_ADDR_SET))
- get_frt_addr(l4);
+ stream_sock_get_to_addr(&l4->si[0]);
switch (l4->si[0].addr.to.ss_family) {
case AF_INET:
pattern_fetch_dst(struct proxy *px, struct session *l4, void *l7, int dir,
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
- if (!(l4->flags & SN_FRT_ADDR_SET))
- get_frt_addr(l4);
+ stream_sock_get_to_addr(&l4->si[0]);
if (l4->si[0].addr.to.ss_family != AF_INET)
return 0;
pattern_fetch_dst6(struct proxy *px, struct session *l4, void *l7, int dir,
const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
{
- if (!(l4->flags & SN_FRT_ADDR_SET))
- get_frt_addr(l4);
+ stream_sock_get_to_addr(&l4->si[0]);
if (l4->si[0].addr.to.ss_family != AF_INET6)
return 0;
acl_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
- if (!(l4->flags & SN_FRT_ADDR_SET))
- get_frt_addr(l4);
+ stream_sock_get_to_addr(&l4->si[0]);
if (!(temp_pattern.data.integer = get_host_port(&l4->si[0].addr.to)))
return 0;
pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir,
const struct pattern_arg *arg, int i, union pattern_data *data)
{
- if (!(l4->flags & SN_FRT_ADDR_SET))
- get_frt_addr(l4);
+ stream_sock_get_to_addr(&l4->si[0]);
if (!(data->integer = get_host_port(&l4->si[0].addr.to)))
return 0;
s->si[0].err_loc = NULL;
s->si[0].connect = NULL;
s->si[0].release = NULL;
+ s->si[0].get_src = getpeername;
+ s->si[0].get_dst = getsockname;
clear_target(&s->si[0].target);
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
s->si[1].err_loc = NULL;
s->si[1].connect = NULL;
s->si[1].release = NULL;
+ s->si[1].get_src = NULL;
+ s->si[1].get_dst = NULL;
clear_target(&s->si[1].target);
s->si[1].shutr = stream_int_shutr;
s->si[1].shutw = stream_int_shutw;