Hi Willy,

Thank you once again for all the detail reply.

On Wed, May 29, 2019 at 1:49 PM Willy Tarreau <[email protected]> wrote:
>
> Hi Alec,
>
> On Thu, May 23, 2019 at 12:43:54AM +0800, Alec Liu wrote:
> > Finally got sometime to have the patch revised.
>
> And finally got some time to review it :-)
>
> > I am reusing the "send_proxy_ofs" right now.
>
> OK.
>
> > Due to it was used as some kind of flag for send Proxy Protocol in some 
> > places.
> > I have to replace those usage to check the srv->pp_opts.
>
> Hmmm this will break health checks then, since you don't know whether a
> connection is made for data traffic or for a check. That makes me think
> that we've been quite annoyed for a while with these problems of finding
> all relevant connection parameters, and that maybe it could be useful to
> think about defining a "connection settings" structure with a lot of
> stuff that we want to use in various situations. A server would then
> have 2 or 3 of these (one for regular traffic or dataplane, one for
> health checks, one for agent checks). We could then use this for the
> source bindings, TLS/PP options etc. When setting up a connection, we'd
> just have to pass a pointer to the desired structure to provide all the
> settings. This definitely is something to think about for 2.1.
>

That should be able to make things more clear and easier to understand
for someone like
me new to the project. But that, I will try to read the code more
carefully to understand
how it works, and will have those changes reversed according to your comments.

> > From 6767c73a40a9d242cce061cc7feaf480ad416314 Mon Sep 17 00:00:00 2001
> > From: Alexander Liu <[email protected]>
> > Date: Wed, 22 May 2019 19:44:48 +0800
> > Subject: [PATCH] MEDIUM: connection: Upstream SOCKS4 proxy support
> >
> > Have "socks4" and "check-via-socks4" server keyword added.
> > Implement handshake with SOCKS4 proxy server for tcp stream connection.
> > See issue #82.
> >
> > I have the "SOCKS: A protocol for TCP proxy across firewalls" doc found
> > at openssh's website under OpenSSH Sprcifications along with other RFCs,
> > at "https://www.openssh.com/specs.html";,
> > and "https://www.openssh.com/txt/socks4.protocol";.
> >
> > OpenSSH is using GPL, so I believe it should be fine to have the doc here.
>   ^^^^^^^^^^^^^^^^^^^^^
>
> It's written exactly the opposite on their site and in the license file :-)
>
> LICENSE:
>   "OpenSSH contains no GPL code."
>
> Well, I think you'll have to find the license covering the doc (probably
> BSD), include it in the doc/ directory and mention in the LICENSE file that
> this doc is provided under that license. Or we consider that it's too much
> hassle for just a protocol specification and you simply put a link to a
> stable URL in the commit message, which will be much simpler (and will also
> support fixes to the spec, that a copy doesn't provide).
>
Sorry for missing the license.

Due to it is a very old specification, most link just not working
well, that's why I try
to have the full text included at first place, and I have been try to
send email to the
author, but those email address just not working anymore, any way I
will leave the url
"https://www.openssh.com/txt/socks4.protocol"; first but the full text.

> > diff --git a/include/proto/connection.h b/include/proto/connection.h
> > index ede372638..915be87bf 100644
> > --- a/include/proto/connection.h
> > +++ b/include/proto/connection.h
> > @@ -60,6 +60,10 @@ int conn_sock_send(struct connection *conn, const void 
> > *buf, int len, int flags)
> >  /* drains any pending bytes from the socket */
> >  int conn_sock_drain(struct connection *conn);
> >
> > +/* scoks4 proxy handshake */
> > +int conn_send_socks4_proxy_request(struct connection *conn);
> > +int conn_recv_socks4_proxy_response(struct connection *conn);
> > +
> >  /* returns true is the transport layer is ready */
> >  static inline int conn_xprt_ready(const struct connection *conn)
> >  {
> > @@ -889,6 +893,11 @@ static inline const char *conn_err_code_str(struct 
> > connection *c)
> >       case CO_ER_SSL_HANDSHAKE_HB: return "SSL handshake failure after 
> > heartbeat";
> >       case CO_ER_SSL_KILLED_HB: return "Stopped a TLSv1 heartbeat attack 
> > (CVE-2014-0160)";
> >       case CO_ER_SSL_NO_TARGET: return "Attempt to use SSL on an unknown 
> > target (internal error)";
> > +
> > +     case CO_ER_SOCKS4_SEND:    return "SOCKS4 Proxy write error during 
> > handshake";
> > +     case CO_ER_SOCKS4_RECV:    return "SOCKS4 Proxy read error during 
> > handshake";
> > +     case CO_ER_SOCKS4_DENY:    return "SOCKS4 Proxy deny the request";
>                                                         ^^^^ denied
>
> > +     case CO_ER_SOCKS4_ABORT:   return "SOCKS4 Proxy handshake aborted by 
> > server";
> >       }
> >       return NULL;
> >  }
> > diff --git a/include/types/connection.h b/include/types/connection.h
> > index be590f098..9a362f05d 100644
> > --- a/include/types/connection.h
> > +++ b/include/types/connection.h
> > @@ -47,6 +47,15 @@ struct server;
> >  struct session;
> >  struct pipe;
> >
> > +/* socks4 upstream proxy definitions */
> > +struct socks4_request {
> > +     uint8_t version;        /* SOCKS version number, 1 byte, must be 0x04 
> > for this version */
> > +     uint8_t command;        /* 0x01 = establish a TCP/IP stream 
> > connection */
> > +     uint16_t port;          /* port number, 2 bytes (in network byte 
> > order) */
> > +     uint32_t ip;            /* IP address, 4 bytes (in network byte 
> > order) */
> > +     char user_id[8];        /* the user ID string, variable length, 
> > terminated with a null (0x00); Using "HAProxy\0" */
> > +};
> > +
> >  /* Note: subscribing to these events is only valid after the caller has 
> > really
> >   * attempted to perform the operation, and failed to proceed or complete.
> >   */
> > @@ -155,8 +164,8 @@ enum {
> >
> >       CO_FL_EARLY_SSL_HS  = 0x00004000,  /* We have early data pending, 
> > don't start SSL handshake yet */
> >       CO_FL_EARLY_DATA    = 0x00008000,  /* At least some of the data are 
> > early data */
> > -     /* unused : 0x00010000 */
> > -     /* unused : 0x00020000 */
> > +     CO_FL_SOCKS4_SEND   = 0x00010000,  /* handshaking with upstream 
> > SOCKS4 proxy, going to send the handshake */
> > +     CO_FL_SOCKS4_RECV   = 0x00020000,  /* handshaking with upstream 
> > SOCKS4 proxy, going to check if handshake succeed */
> >
> >       /* flags used to remember what shutdown have been performed/reported 
> > */
> >       CO_FL_SOCK_RD_SH    = 0x00040000,  /* SOCK layer was notified about 
> > shutr/read0 */
> > @@ -182,7 +191,7 @@ enum {
> >       CO_FL_ACCEPT_CIP    = 0x08000000,  /* receive a valid NetScaler 
> > Client IP header */
> >
> >       /* below we have all handshake flags grouped into one */
> > -     CO_FL_HANDSHAKE     = CO_FL_SEND_PROXY | CO_FL_SSL_WAIT_HS | 
> > CO_FL_ACCEPT_PROXY | CO_FL_ACCEPT_CIP,
> > +     CO_FL_HANDSHAKE     = CO_FL_SEND_PROXY | CO_FL_SSL_WAIT_HS | 
> > CO_FL_ACCEPT_PROXY | CO_FL_ACCEPT_CIP | CO_FL_SOCKS4_SEND | 
> > CO_FL_SOCKS4_RECV,
> >
> >       /* when any of these flags is set, polling is defined by socket-layer
> >        * operations, as opposed to data-layer. Transport is explicitly not
> > @@ -205,8 +214,10 @@ enum {
> >        * must be done after clearing this flag.
> >        */
> >       CO_FL_XPRT_TRACKED  = 0x80000000,
> > -};
> >
> > +     /* below we have all SOCKS handshake flags grouped into one */
> > +     CO_FL_SOCKS4        = CO_FL_SOCKS4_SEND | CO_FL_SOCKS4_RECV,
> > +};
>
> Just so that you know, Olivier is finishing his changes in this area to
> make SSL totally self-sustaining (will be needed for QUIC) so at some
> point we'll have a conflict here. He'll probably know how to adapt this
> however.

I will try to read the code from Olivier for the SSL part , to learn
more about it.

>
> > diff --git a/include/types/server.h b/include/types/server.h
> > index 0d53d2600..219f5ab1d 100644
> > --- a/include/types/server.h
> > +++ b/include/types/server.h
> > @@ -141,6 +141,7 @@ enum srv_initaddr {
> >  #define SRV_F_AGENTADDR    0x0080        /* this server has a agent addr 
> > configured */
> >  #define SRV_F_COOKIESET    0x0100        /* this server has a cookie 
> > configured, so don't generate dynamic cookies */
> >  #define SRV_F_FASTOPEN     0x0200        /* Use TCP Fast Open to connect 
> > to server */
> > +#define SRV_F_SOCKS4_PROXY 0x0400        /* this server uses SOCKS4 proxy 
> > */
>
> So you'll need a distinct flag for the checks.

Then I will have the "SRV_F_SOCKS4_PROXY"  use with the data traffic,
and "CO_FL_SEND_SOCKS4" for the check.

>
> > diff --git a/src/backend.c b/src/backend.c
> > index 467ef57a9..09623e884 100644
> > --- a/src/backend.c
> > +++ b/src/backend.c
> > @@ -1532,6 +1532,10 @@ int connect_server(struct stream *s)
> >               }
> >
> >               assign_tproxy_address(s);
> > +
> > +             if (srv && (srv->flags & SRV_F_SOCKS4_PROXY)) {
> > +                     srv_conn->send_proxy_ofs = 1;
> > +             }
> >       }
> >       else if (!conn_xprt_ready(srv_conn)) {
> >               if (srv_conn->mux->reset)
> > diff --git a/src/checks.c b/src/checks.c
> > index d264aecf8..5dbfd0e9a 100644
> > --- a/src/checks.c
> > +++ b/src/checks.c
> > @@ -1612,6 +1612,15 @@ static int connect_conn_chk(struct task *t)
> >               conn->addr.to = s->addr;
> >       }
> >
> > +     if (s->check.via_socks4) {
> > +             if (s->flags & SRV_F_SOCKS4_PROXY) {
> > +                     conn->send_proxy_ofs = 1;
> > +                     conn->flags |= CO_FL_SOCKS4_SEND;
> > +             }
> > +     }else{
> > +             conn->flags &= (~CO_FL_SOCKS4);
> > +     }
> > +
> >       proto = protocol_by_family(conn->addr.to.ss_family);
> >       conn->target = &s->obj_type;
> >
> > diff --git a/src/connection.c b/src/connection.c
> > index 908d098e4..e0663534b 100644
> > --- a/src/connection.c
> > +++ b/src/connection.c
> > @@ -27,6 +27,8 @@
> >  #include <proto/sample.h>
> >  #include <proto/ssl_sock.h>
> >
> > +#include <common/debug.h>
> > +
> >  DECLARE_POOL(pool_head_connection, "connection",  sizeof(struct 
> > connection));
> >  DECLARE_POOL(pool_head_connstream, "conn_stream", sizeof(struct 
> > conn_stream));
> >
> > @@ -69,6 +71,16 @@ void conn_fd_handler(int fd)
> >               if (unlikely(conn->flags & CO_FL_ERROR))
> >                       goto leave;
> >
> > +             if (conn->flags & CO_FL_SOCKS4_SEND) {
> > +                     //Going to send the request to the socks4 proxy
> > +                     conn_send_socks4_proxy_request(conn);
> > +                     goto leave;
> > +             }
>
> Here you're immediately quitting, I suppose it's because you're expecting
> to wait for a response ? In any case it's not correct, you should proceed
> like for others, i.e. "if (!conn_send_...) goto leave", and leave it to
> the next stage to decide to wait. Otherwise you risk to not even subscribe
> to receive events because you don't try. Also in some rare cases (localhost,
> VM, heavily loaded machine), you might be scheduled out for a while and have
> the response ready when you get back here and you want to be sure not to
> miss such events either.
Yep, I am trying to get the response at once. Got your point, will have it fix.

>
> > +             if (conn->flags & CO_FL_SOCKS4_RECV)
> > +                     if (!conn_recv_socks4_proxy_response(conn))
> > +                             goto leave;
> > +
> >               if (conn->flags & CO_FL_ACCEPT_CIP)
> >                       if (!conn_recv_netscaler_cip(conn, CO_FL_ACCEPT_CIP))
> >                               goto leave;
> > @@ -959,6 +971,182 @@ int conn_recv_netscaler_cip(struct connection *conn, 
> > int flag)
> >       return 0;
> >  }
> >
> > +
> > +int conn_send_socks4_proxy_request(struct connection *conn)
> > +{
> > +     struct socks4_request req_line;
> > +
> > +     /* we might have been called just after an asynchronous shutw */
> > +     if (conn->flags & CO_FL_SOCK_WR_SH)
> > +             goto out_error;
>
> I *think* (but could be wrong) that when you have CO_FL_ERROR, you also
> have the shutdown flag set. In this case be careful, as you're overwriting
> the error code which might already have been set by the layer which actually
> faced the error Either you first check for CO_FL_ERROR and you don't set
> your code when it's set, or you can decide to conditionally set your error
> code only when conn->err_code is not set. The former is cleaner, the latter
> is fine since already done at other places.
>

Will have it checked before setting the conn->err_code.

> > +     if (!conn_ctrl_ready(conn))
> > +             goto out_error;
>
> It's probably the same here.
>
> > +     req_line.version = 0x04;
> > +     req_line.command = 0x01;
> > +     req_line.port = get_net_port(&(conn->addr.to));
> > +     req_line.ip = is_inet_addr(&(conn->addr.to));
> > +     strcpy(req_line.user_id,"HAProxy");
>
> Just a small nit, you can use memcpy(req_line.user_id, "HAProxy\0", 8) here
> instead, it will make it easier for the compiler to verify that it fits and
> will avoid a warning on systems where strcpy() systematically emits one.
I see.

>
> > +     if (conn->send_proxy_ofs > 0) {
> > +             /*
> > +              * This is the first call to send the request
> > +              */
> > +             conn->send_proxy_ofs = -((int)(sizeof(req_line)));
> > +     }
> > +
> > +     while (conn->send_proxy_ofs < 0) {
> > +             int ret = 0;
> > +
> > +             /* we are sending the socks4_req_line here. If the data layer
> > +              * has a pending write, we'll also set MSG_MORE.
> > +              */
> > +             ret = conn_sock_send(
> > +                             conn,
> > +                             ((char *)(&req_line)) + 
> > (sizeof(req_line)+conn->send_proxy_ofs),
> > +                             -conn->send_proxy_ofs,
> > +                             (conn->flags & CO_FL_XPRT_WR_ENA) ? MSG_MORE 
> > : 0);
> > +
> > +             DPRINTF(stderr, "SOCKS PROXY HS FD[%04X]: Before send remain 
> > is [%d], sent [%d]\n",
> > +                             conn->handle.fd, -conn->send_proxy_ofs, ret);
> > +
> > +             if (ret < 0) {
> > +                     goto out_error;
> > +             }
> > +
> > +             conn->send_proxy_ofs += ret; /* becomes zero once complete */
> > +             if (conn->send_proxy_ofs != 0) {
> > +                     goto out_wait;
> > +             }
> > +
> > +             /* OK we've the whole request sent */
> > +             conn->flags &= (~CO_FL_SOCKS4_SEND);
>                                ^                  ^
> Please avoid these useless parenthesis above, I noticed them at a few
> places and they are even inconsistent (you don't have them below for
> example).
>
I just want to make it easier to read, "LEFTPART &= RIGHTPART", both
left and right will be a whole one, but
"LEFTPART &= RIGHTPART1 x RIGHTPART2 x RIGHTPART3".

> > +
> > +             /* Turn to receiving response */
> > +             conn->flags |= CO_FL_SOCKS4_RECV;
>
> This one should be set where you set CO_FL_SOCKS4_SEND because when
> you decide you'll send it, you also know you want to wait for the
> response.
>
Yep you are right, when it sending the socks4 request, it is waiting for reply.
But if the sending part get failed, it won't going to expect for the
response, and
we should not getting anything before sending the request, if we do,
it should be
something wrong.

May be it should be ok to have both flags set at the same time for most cases,
but I think setting it separately will be fine too.

> > +             /* mark it for receive the response */
> > +             __conn_sock_want_recv(conn);
> > +             break;
> > +     }
> > +
> > +     if (conn->flags & CO_FL_SEND_PROXY) {
> > +             /*
> > +              * Get the send_proxy_ofs ready for the send_proxy due to we 
> > are
> > +              * reusing the "send_proxy_ofs", and SOCKS4 handshake should 
> > be done
> > +              * before sending PROXY Protocol.
> > +              */
> > +             conn->send_proxy_ofs = 1;
>
> looks good.
>
> > +     }
> > +     return 1;
> > +
> > + out_error:
> > +     /* Write error on the file descriptor */
> > +     conn->flags |= CO_FL_ERROR;
> > +     conn->err_code = CO_ER_SOCKS4_SEND;
> > +     return 0;
> > +
> > + out_wait:
> > +     __conn_sock_stop_recv(conn);
> > +     return 0;
> > +}
> > +
> > +int conn_recv_socks4_proxy_response(struct connection *conn)
> > +{
> > +     char line[SOCKS4_HS_RSP_LEN];
> > +     int ret;
> > +
> > +     /* we might have been called just after an asynchronous shutr */
> > +     if (conn->flags & CO_FL_SOCK_RD_SH)
> > +             goto fail;
> > +
> > +     if (!conn_ctrl_ready(conn))
> > +             goto fail;
> > +
> > +     if (!fd_recv_ready(conn->handle.fd))
> > +             return 0;
> > +
> > +     do {
> > +             /* SOCKS4 Proxy request granted server response, 0x00 | 0x5A 
> > | 0x00 0x00 | 0x00 0x00 0x00 0x00
> > +              * Try to peek into it, before all 8 bytes of response ready.
> > +              */
> > +             ret = recv(conn->handle.fd, line, SOCKS4_HS_RSP_LEN, 
> > MSG_PEEK);
> > +
> > +             if (ret == 0) {
> > +                     /* the socket has been closed or shutdown for send */
> > +                     DPRINTF(stderr, "SOCKS PROXY HS FD[%04X]: Received 
> > ret[%d], errno[%d], looks like the socket has been closed or shutdown for 
> > send\n",
> > +                                     conn->handle.fd, ret, errno);
> > +                     conn->err_code = CO_ER_SOCKS4_RECV;
> > +                     goto fail;
> > +             }
> > +
> > +             if (ret > 0) {
> > +                     if (ret == SOCKS4_HS_RSP_LEN){
> > +                             DPRINTF(stderr, "SOCKS PROXY HS FD[%04X]: 
> > Received 8 bytes, the response is [%02X|%02X|%02X %02X|%02X %02X %02X 
> > %02X]\n",
> > +                                             conn->handle.fd, line[0], 
> > line[1], line[2], line[3], line[4], line[5], line[6], line[7]);
> > +                     }else{
> > +                             DPRINTF(stderr, "SOCKS PROXY HS FD[%04X]: 
> > Received ret[%d], first byte is [%02X], last bye is [%02X]\n", 
> > conn->handle.fd, ret, line[0], line[ret-1]);
> > +                     }
> > +             } else {
> > +                     DPRINTF(stderr, "SOCKS PROXY HS FD[%04X]: Received 
> > ret[%d], errno[%d]\n", conn->handle.fd, ret, errno);
> > +             }
> > +
> > +             if (ret < 0) {
> > +                     if (errno == EINTR) {
> > +                             continue;
> > +                     }
> > +                     if (errno == EAGAIN) {
> > +                             fd_cant_recv(conn->handle.fd);
> > +                             return 0;
> > +                     }
> > +                     goto recv_abort;
> > +             }
> > +     } while (0);
> > +
> > +     if (ret < SOCKS4_HS_RSP_LEN) {
> > +             /* Missing data. Since we're using MSG_PEEK, we can only poll 
> > again if
> > +              * we have not able to read enough data.
> > +              */
> > +             fd_cant_recv(conn->handle.fd);
> > +             return 0;
> > +     }
> > +
> > +     if (line[1] != 0x5A) {
>
> Please either use #define/enums if this corresponds to something particular,
> or at least indicate in a comment what you're trying to verify (what's in
> line[1] and what 0x5A corresponds to).
Actually I have comment for it at " /* SOCKS4 Proxy request granted
server response, 0x00 | 0x5A | 0x00 0x00 | 0x00 0x00 0x00 0x00".
Anyway, I will make thing clearer here.

>
> > +             conn->flags &= (~CO_FL_SOCKS4_RECV);
> > +
> > +             DPRINTF(stderr, "SOCKS PROXY HS FD[%04X]: FAIL, the response 
> > is [%02X|%02X|%02X %02X|%02X %02X %02X %02X]\n",
> > +                             conn->handle.fd, line[0], line[1], line[2], 
> > line[3], line[4], line[5], line[6], line[7]);
> > +             conn->err_code = CO_ER_SOCKS4_DENY;
> > +             goto fail;
> > +     }
> > +
> > +     /* remove the 8 bytes response from the stream */
> > +     do {
> > +             ret = recv(conn->handle.fd, line, SOCKS4_HS_RSP_LEN, 0);
> > +             if (ret < 0 && errno == EINTR) {
> > +                     continue;
> > +             }
> > +             if (ret != SOCKS4_HS_RSP_LEN) {
> > +                     conn->err_code = CO_ER_SOCKS4_RECV;
> > +                     goto fail;
> > +             }
> > +     } while (0);
> > +
> > +     conn->flags &= (~CO_FL_SOCKS4_RECV);
>                        ^                  ^
> > +     return 1;
> > +
> > + recv_abort:
> > +     conn->err_code = CO_ER_SOCKS4_ABORT;
> > +     conn->flags |= (CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH);
>                        ^                                   ^
> > +     goto fail;
> > +
> > + fail:
> > +     __conn_sock_stop_both(conn);
> > +     conn->flags |= CO_FL_ERROR;
> > +     return 0;
> > +}
> > +
> >  /* Note: <remote> is explicitly allowed to be NULL */
> >  int make_proxy_line(char *buf, int buf_len, struct server *srv, struct 
> > connection *remote)
> >  {
> > diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c
> > index 97a93480a..af77f17ef 100644
> > --- a/src/proto_sockpair.c
> > +++ b/src/proto_sockpair.c
> > @@ -240,12 +240,19 @@ int send_fd_uxst(int fd, int send_fd)
> >  static int sockpair_connect_server(struct connection *conn, int flags)
> >  {
> >       int sv[2], fd, dst_fd = -1;
> > +     struct server *srv;
> >
> >       /* the FD is stored in the sockaddr struct */
> >       dst_fd = ((struct sockaddr_in *)&conn->addr.to)->sin_addr.s_addr;
> >
> > -     if (obj_type(conn->target) != OBJ_TYPE_PROXY &&
> > -         obj_type(conn->target) != OBJ_TYPE_SERVER) {
> > +     switch (obj_type(conn->target)) {
> > +     case OBJ_TYPE_PROXY:
> > +             srv = NULL;
> > +             break;
> > +     case OBJ_TYPE_SERVER:
> > +             srv = objt_server(conn->target);
> > +             break;
> > +     default:
> >               conn->flags |= CO_FL_ERROR;
> >               return SF_ERR_INTERNAL;
> >       }
> > @@ -289,7 +296,7 @@ static int sockpair_connect_server(struct connection 
> > *conn, int flags)
> >       }
> >
> >       /* if a send_proxy is there, there are data */
> > -     if (conn->send_proxy_ofs)
> > +     if (srv && srv->pp_opts)
>
> So here it breaks the checks, they will always run with the same proxy
> protocol settings as the data traffic. I think that you should keep this
> test as-is since you're still sending something.
>
Will keep it.

> >               flags |= CONNECT_HAS_DATA;
> >
> >       if (global.tune.server_sndbuf)
> > @@ -315,7 +322,7 @@ static int sockpair_connect_server(struct connection 
> > *conn, int flags)
> >       conn->flags |= CO_FL_ADDR_TO_SET;
> >
> >       /* Prepare to send a few handshakes related to the on-wire protocol. 
> > */
> > -     if (conn->send_proxy_ofs)
> > +     if (srv && srv->pp_opts)
> >               conn->flags |= CO_FL_SEND_PROXY;
>
> And here, we should just move the CO_FL_SEND_PROXY flag setting to the
> place where send_proxy_ofs is set and remove this test. It looks like
> checks already do it correctly and that it's only needed in backend.c.
> Then with this it becomes clean : the one who wants to emit a header
> just sets his CO_FL_SEND_XXX flag with send_proxy_ofs=1, then each other
> one in turn will simply have to recheck this. We could even go slightly
> further and let the connect() functions set send_proxy_ofs to 1 themselves
> when any of the SEND flags are set so that the upper layer only has to
> focus on setting the appropriate flags.
>
> Please do that in a separate preliminary patch, which will allow to
> bisect later if some problems are reported after your patches are merged.
>
I will keep it this way first, and then try to submit another patch for the idea
to make the "send_proxy_ofs" clearer.

> >       conn_ctrl_init(conn);       /* registers the FD */
> > diff --git a/src/proto_tcp.c b/src/proto_tcp.c
> > index 95068ee6c..d5471c8ef 100644
> > --- a/src/proto_tcp.c
> > +++ b/src/proto_tcp.c
> > @@ -294,6 +294,7 @@ int tcp_connect_server(struct connection *conn, int 
> > flags)
> >       struct proxy *be;
> >       struct conn_src *src;
> >       int use_fastopen = 0;
> > +     int ret;
> >
> >       conn->flags |= CO_FL_WAIT_L4_CONN; /* connection in progress */
> >
> > @@ -492,7 +493,7 @@ int tcp_connect_server(struct connection *conn, int 
> > flags)
> >        */
> >       if (flags & (CONNECT_DELACK_ALWAYS) ||
> >           ((flags & CONNECT_DELACK_SMART_CONNECT ||
> > -           (flags & CONNECT_HAS_DATA) || conn->send_proxy_ofs) &&
> > +           (flags & CONNECT_HAS_DATA) || (srv && srv->pp_opts)) &&
>
> So same issue here with pp_opts.
Will reverse it.

>
> >            (be->options2 & PR_O2_SMARTCON)))
> >                  setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &zero, 
> > sizeof(zero));
> >  #endif
> > @@ -514,7 +515,12 @@ int tcp_connect_server(struct connection *conn, int 
> > flags)
> >       if (global.tune.server_rcvbuf)
> >                  setsockopt(fd, SOL_SOCKET, SO_RCVBUF, 
> > &global.tune.server_rcvbuf, sizeof(global.tune.server_rcvbuf));
> >
> > -     if (connect(fd, (struct sockaddr *)&conn->addr.to, 
> > get_addr_len(&conn->addr.to)) == -1) {
> > +     if (srv->flags & SRV_F_SOCKS4_PROXY) {
>
> Same problem with no distinction between check and traffic. Please use
> conn->flags & CO_FL_SEND_SOCKS4 instead since it will already have been
> set as needed.

Got it.

>
> > +             ret = connect(fd, (struct sockaddr *)&(srv->socks4_addr), 
> > get_addr_len(&(srv->socks4_addr)));
> > +     } else {
> > +             ret = connect(fd, (struct sockaddr *)&conn->addr.to, 
> > get_addr_len(&conn->addr.to));
> > +     }
> > +     if (ret == -1) {
>
> I haven't looked at the emitted code, but I suspect it will be cleaner if you
> add this :
>
>     struct sockaddr_storage *addr;
>     ...
>     addr = (conn->flags & CO_FL_SEND_SOCKS4) ? &srv->socks4_addr : 
> &conn->addr.to;
>     if (connect(fd, (const struct sockaddr *)addr, get_addr_len(addr)) == -1) 
> {
>     ...
>
Ok, I will do it in that way.

> > @@ -568,9 +574,13 @@ int tcp_connect_server(struct connection *conn, int 
> > flags)
> >       conn->flags |= CO_FL_ADDR_TO_SET;
> >
> >       /* Prepare to send a few handshakes related to the on-wire protocol. 
> > */
> > -     if (conn->send_proxy_ofs)
> > +     if (srv && srv->pp_opts)
> >               conn->flags |= CO_FL_SEND_PROXY;
>
> Same comment as for the socketpair sockets here.
Got it.

>
> > +     /* Prepare to send socks proxy related handshakes */
> > +     if (srv && srv->flags & SRV_F_SOCKS4_PROXY)
> > +             conn->flags |= CO_FL_SOCKS4_SEND;
>
> and here.
Got it.

>
> > diff --git a/src/proto_uxst.c b/src/proto_uxst.c
> > index 42e0dc878..3f8213347 100644
> > --- a/src/proto_uxst.c
> > +++ b/src/proto_uxst.c
> > @@ -510,7 +510,7 @@ static int uxst_connect_server(struct connection *conn, 
> > int flags)
> >       }
> >
> >       /* if a send_proxy is there, there are data */
> > -     if (conn->send_proxy_ofs)
> > +     if (srv && srv->pp_opts)
> >               flags |= CONNECT_HAS_DATA;
> >
> >       if (global.tune.server_sndbuf)
> > @@ -566,7 +566,7 @@ static int uxst_connect_server(struct connection *conn, 
> > int flags)
> >       conn->flags |= CO_FL_ADDR_TO_SET;
> >
> >       /* Prepare to send a few handshakes related to the on-wire protocol. 
> > */
> > -     if (conn->send_proxy_ofs)
> > +     if (srv && srv->pp_opts)
> >               conn->flags |= CO_FL_SEND_PROXY;
>
> Same comments here. You didn't implement SOCKS4 over unix sockets ?
> Is there any particular reason or was it just forgotten ?

Actually, the socks4 protocol is just for TCP normally.

>
>
> Thanks,
> Willy

Reply via email to