/* This callback is used to send a valid PROXY protocol line to a socket being * established. It returns 0 if it fails in a fatal way or needs to poll to go * further, otherwise it returns non-zero and removes itself from the connection's * flags (the bit is provided in <flag> by the caller). It is designed to be * called by the connection handler and relies on it to commit polling changes. * Note that it can emit a PROXY line by relying on the other end's address * when the connection is attached to a stream interface, or by resolving the * local address otherwise (also called a LOCAL line). */ int conn_si_send_proxy(struct connection *conn, unsigned int flag) { /* we might have been called just after an asynchronous shutw */ if (conn->flags & CO_FL_SOCK_WR_SH) goto out_error; if (!conn_ctrl_ready(conn)) goto out_error; if (!fd_send_ready(conn->t.sock.fd)) goto out_wait; /* If we have a PROXY line to send, we'll use this to validate the * connection, in which case the connection is validated only once * we've sent the whole proxy line. Otherwise we use connect(). */ while (conn->send_proxy_ofs) { int ret; /* The target server expects a PROXY line to be sent first. * If the send_proxy_ofs is negative, it corresponds to the * offset to start sending from then end of the proxy string * (which is recomputed every time since it's constant). If * it is positive, it means we have to send from the start. * We can only send a "normal" PROXY line when the connection * is attached to a stream interface. Otherwise we can only * send a LOCAL line (eg: for use with health checks). */ if (conn->data == &si_conn_cb) { struct stream_interface *si = conn->owner; struct connection *remote = objt_conn(si->ob->prod->end); ret = make_proxy_line(trash.str, trash.size, objt_server(conn->target), remote); } else { /* The target server expects a LOCAL line to be sent first. Retrieving * local or remote addresses may fail until the connection is established. */ conn_get_from_addr(conn); if (!(conn->flags & CO_FL_ADDR_FROM_SET)) goto out_wait; conn_get_to_addr(conn); if (!(conn->flags & CO_FL_ADDR_TO_SET)) goto out_wait; ret = make_proxy_line(trash.str, trash.size, objt_server(conn->target), conn); } if (!ret) goto out_error; if (conn->send_proxy_ofs > 0) conn->send_proxy_ofs = -ret; /* first call */ /* we have to send trash from (ret+sp for -sp bytes). If the * data layer has a pending write, we'll also set MSG_MORE. */ ret = send(conn->t.sock.fd, trash.str + ret + conn->send_proxy_ofs, -conn->send_proxy_ofs, (conn->flags & CO_FL_DATA_WR_ENA) ? MSG_MORE : 0); if (ret == 0) goto out_wait; if (ret < 0) { if (errno == EAGAIN || errno == ENOTCONN) goto out_wait; if (errno == EINTR) continue; conn->flags |= CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH; goto out_error; } conn->send_proxy_ofs += ret; /* becomes zero once complete */ if (conn->send_proxy_ofs != 0) goto out_wait; /* OK we've sent the whole line, we're connected */ break; } /* The connection is ready now, simply return and let the connection * handler notify upper layers if needed. */ if (conn->flags & CO_FL_WAIT_L4_CONN) conn->flags &= ~CO_FL_WAIT_L4_CONN; conn->flags &= ~flag; return 1; out_error: /* Write error on the file descriptor */ conn->flags |= CO_FL_ERROR; return 0; out_wait: __conn_sock_stop_recv(conn); fd_cant_send(conn->t.sock.fd); return 0; }
/* * This function is called to send buffer data to a stream socket. * It returns -1 in case of unrecoverable error, 0 if the caller needs to poll * before calling it again, otherwise 1. If a pipe was associated with the * buffer and it empties it, it releases it as well. */ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b) { int write_poll = MAX_WRITE_POLL_LOOPS; int retval = 1; int ret, max; if (unlikely(si->send_proxy_ofs)) { /* The target server expects a PROXY line to be sent first. * If the send_proxy_ofs is negative, it corresponds to the * offset to start sending from then end of the proxy string * (which is recomputed every time since it's constant). If * it is positive, it means we have to send from the start. */ ret = make_proxy_line(trash, sizeof(trash), &b->prod->addr.from, &b->prod->addr.to); if (!ret) return -1; if (si->send_proxy_ofs > 0) si->send_proxy_ofs = -ret; /* first call */ /* we have to send trash from (ret+sp for -sp bytes) */ ret = send(si->fd, trash + ret + si->send_proxy_ofs, -si->send_proxy_ofs, (b->flags & BF_OUT_EMPTY) ? 0 : MSG_MORE); if (ret > 0) { if (fdtab[si->fd].state == FD_STCONN) fdtab[si->fd].state = FD_STREADY; si->send_proxy_ofs += ret; /* becomes zero once complete */ b->flags |= BF_WRITE_NULL; /* connect() succeeded */ } else if (ret == 0 || errno == EAGAIN) { /* nothing written, we need to poll for write first */ return 0; } else { /* bad, we got an error */ return -1; } } #if defined(CONFIG_HAP_LINUX_SPLICE) while (b->pipe) { ret = splice(b->pipe->cons, NULL, si->fd, NULL, b->pipe->data, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); if (ret <= 0) { if (ret == 0 || errno == EAGAIN) { retval = 0; return retval; } /* here we have another error */ retval = -1; return retval; } b->flags |= BF_WRITE_PARTIAL; b->pipe->data -= ret; if (!b->pipe->data) { put_pipe(b->pipe); b->pipe = NULL; break; } if (--write_poll <= 0) return retval; /* The only reason we did not empty the pipe is that the output * buffer is full. */ return 0; } /* At this point, the pipe is empty, but we may still have data pending * in the normal buffer. */ #endif if (!b->send_max) { b->flags |= BF_OUT_EMPTY; return retval; } /* when we're in this loop, we already know that there is no spliced * data left, and that there are sendable buffered data. */ while (1) { if (b->r > b->w) max = b->r - b->w; else max = b->data + b->size - b->w; /* limit the amount of outgoing data if required */ if (max > b->send_max) max = b->send_max; /* check if we want to inform the kernel that we're interested in * sending more data after this call. We want this if : * - we're about to close after this last send and want to merge * the ongoing FIN with the last segment. * - we know we can't send everything at once and must get back * here because of unaligned data * - there is still a finite amount of data to forward * The test is arranged so that the most common case does only 2 * tests. */ if (MSG_NOSIGNAL && MSG_MORE) { unsigned int send_flag = MSG_DONTWAIT | MSG_NOSIGNAL; if ((!(b->flags & BF_NEVER_WAIT) && ((b->to_forward && b->to_forward != BUF_INFINITE_FORWARD) || (b->flags & BF_EXPECT_MORE))) || ((b->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK)) == BF_SHUTW_NOW && (max == b->send_max)) || (max != b->l && max != b->send_max)) { send_flag |= MSG_MORE; } /* this flag has precedence over the rest */ if (b->flags & BF_SEND_DONTWAIT) send_flag &= ~MSG_MORE; ret = send(si->fd, b->w, max, send_flag); } else { int skerr; socklen_t lskerr = sizeof(skerr); ret = getsockopt(si->fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr); if (ret == -1 || skerr) ret = -1; else ret = send(si->fd, b->w, max, MSG_DONTWAIT); } if (ret > 0) { if (fdtab[si->fd].state == FD_STCONN) fdtab[si->fd].state = FD_STREADY; b->flags |= BF_WRITE_PARTIAL; b->w += ret; if (b->w == b->data + b->size) b->w = b->data; /* wrap around the buffer */ b->l -= ret; if (likely(b->l < buffer_max_len(b))) b->flags &= ~BF_FULL; if (likely(!b->l)) /* optimize data alignment in the buffer */ b->r = b->w = b->lr = b->data; b->send_max -= ret; if (!b->send_max) { /* Always clear both flags once everything has been sent, they're one-shot */ b->flags &= ~(BF_EXPECT_MORE | BF_SEND_DONTWAIT); if (likely(!b->pipe)) b->flags |= BF_OUT_EMPTY; break; } /* if the system buffer is full, don't insist */ if (ret < max) break; if (--write_poll <= 0) break; } else if (ret == 0 || errno == EAGAIN) { /* nothing written, we need to poll for write first */ retval = 0; break; } else { /* bad, we got an error */ retval = -1; break; } } /* while (1) */ return retval; }
/* This callback is used to send a valid PROXY protocol line to a socket being * established. It returns 0 if it fails in a fatal way or needs to poll to go * further, otherwise it returns non-zero and removes itself from the connection's * flags (the bit is provided in <flag> by the caller). It is designed to be * called by the connection handler and relies on it to commit polling changes. */ int conn_si_send_proxy(struct connection *conn, unsigned int flag) { struct stream_interface *si = conn->owner; /* we might have been called just after an asynchronous shutw */ if (conn->flags & CO_FL_SOCK_WR_SH) goto out_error; /* If we have a PROXY line to send, we'll use this to validate the * connection, in which case the connection is validated only once * we've sent the whole proxy line. Otherwise we use connect(). */ if (si->send_proxy_ofs) { int ret; /* The target server expects a PROXY line to be sent first. * If the send_proxy_ofs is negative, it corresponds to the * offset to start sending from then end of the proxy string * (which is recomputed every time since it's constant). If * it is positive, it means we have to send from the start. */ ret = make_proxy_line(trash.str, trash.size, &si->ob->prod->conn->addr.from, &si->ob->prod->conn->addr.to); if (!ret) goto out_error; if (si->send_proxy_ofs > 0) si->send_proxy_ofs = -ret; /* first call */ /* we have to send trash from (ret+sp for -sp bytes). If the * data layer has a pending write, we'll also set MSG_MORE. */ ret = send(conn->t.sock.fd, trash.str + ret + si->send_proxy_ofs, -si->send_proxy_ofs, (conn->flags & CO_FL_DATA_WR_ENA) ? MSG_MORE : 0); if (ret == 0) goto out_wait; if (ret < 0) { if (errno == EAGAIN) goto out_wait; goto out_error; } si->send_proxy_ofs += ret; /* becomes zero once complete */ if (si->send_proxy_ofs != 0) goto out_wait; /* OK we've sent the whole line, we're connected */ } /* The connection is ready now, simply return and let the connection * handler notify upper layers if needed. */ if (conn->flags & CO_FL_WAIT_L4_CONN) conn->flags &= ~CO_FL_WAIT_L4_CONN; conn->flags &= ~flag; return 1; out_error: /* Write error on the file descriptor */ conn->flags |= CO_FL_ERROR; return 0; out_wait: __conn_sock_stop_recv(conn); __conn_sock_poll_send(conn); return 0; }