return APR_SUCCESS;
}
+#define ANCIL_FD_BUFFER(n) \
+ struct { \
+ struct cmsghdr h; \
+ int fd[n]; \
+ }
static apr_status_t send_socket(apr_pool_t *p,
apr_socket_t *s,
- apr_socket_t *outbound)
+ apr_socket_t *outbound,
+ apr_socket_t *ctrlsock)
{
apr_status_t rv;
apr_os_sock_t rawsock;
apr_os_sock_t srawsock;
+ apr_os_sock_t sctrlsock;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
char b = '\0', *buf;
+ ANCIL_FD_BUFFER(2) ancil_buf;
{
int mop_fd;
if (rv != APR_SUCCESS) {
return rv;
}
+
+ rv = apr_os_sock_get(&sctrlsock, ctrlsock);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
{
int mop_fd;
iov.iov_base = &b;
iov.iov_len = 1;
- cmsg = apr_palloc(p, sizeof(*cmsg) + sizeof(rawsock));
- cmsg->cmsg_len = sizeof(*cmsg) + sizeof(rawsock);
+ msg.msg_control = &ancil_buf;
+ msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(rawsock) * 2;
+
+ // cmsg = apr_palloc(p, sizeof(*cmsg) + sizeof(rawsock));
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = sizeof(*cmsg) + sizeof(rawsock) * 2;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
- memcpy(CMSG_DATA(cmsg), &rawsock, sizeof(rawsock));
-
- msg.msg_control = cmsg;
- msg.msg_controllen = cmsg->cmsg_len;
+ ((int *)CMSG_DATA(cmsg))[0] = rawsock;
+ ((int *)CMSG_DATA(cmsg))[1] = sctrlsock;
rv = sendmsg(srawsock, &msg, 0);
sprintf(s, "%s%s:%s\n", s, key, value);
}
+#define CTRL_BUFF_MAX_SZ (8*1024)
+
+#define DEFAULT_ENCTYPE "application/x-www-form-urlencoded"
+
+int util_read(request_rec *r, const char **rbuf)
+{
+ int rc;
+
+ if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
+ return rc;
+ }
+
+ if (ap_should_client_block(r)) {
+ char argsbuffer[HUGE_STRING_LEN];
+ int rsize, len_read, rpos=0;
+ long length = r->remaining;
+ *rbuf = (char *)apr_pcalloc(r->pool, length +1);
+
+ while ((len_read = ap_get_client_block(r, argsbuffer,
+sizeof(argsbuffer))) > 0) {
+ if ((rpos + len_read) > length) {
+ rsize = length - rpos;
+ } else {
+ rsize = len_read;
+ }
+
+ memcpy((char *)*rbuf + rpos, argsbuffer, rsize);
+ rpos += rsize;
+ }
+
+ }
+
+ return rc;
+}
+
+int read_post(request_rec *r, const char **data)
+{
+ const char *type;
+ int rc = OK;
+
+ if (r->method_number != M_POST) {
+ return rc;
+ }
+
+ type = apr_table_get(r->headers_in, "Content-Type");
+ if (strcasecmp(type, DEFAULT_ENCTYPE) != 0) {
+ return DECLINED;
+ }
+
+ if ((rc = util_read(r, data)) != OK) {
+ return rc;
+ }
+
+ return OK;
+}
+
+
// TODO: sanitize calloc
static int proxy_fdpass_handler(request_rec *r, proxy_worker *worker,
proxy_server_conf *conf,
apr_socket_t *clientsock;
char *buf;
char *headers_out = NULL;
+ int ctrlrawsock[2];
+ apr_socket_t *ctrlsock = NULL, *clientctrlsock = NULL;
+ apr_size_t wrlen;
+ const char *post_data = NULL;
- if ((headers_out = calloc(8*1024, 1)) != NULL) {
+ if ((headers_out = calloc(CTRL_BUFF_MAX_SZ, 1)) != NULL) {
+ sprintf(headers_out, "The-Request:%s\n", r->the_request);
apr_table_do(headers_builder, headers_out, r->headers_in, NULL);
}
-
+ read_post(r, &post_data);
{
int mop_fd;
close(mop_fd);
}
- /*
- if (headers_out)
- free(headers_out);
- */
if (strncasecmp(url, "fd://", 5) == 0) {
url += 5;
}
return HTTP_INTERNAL_SERVER_ERROR;
}
+ /* create a couple of sockets and pass one to the client for headers and so on */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, ctrlrawsock)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "proxy: FD: Failed create socketpair");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ rv = apr_os_sock_put(&ctrlsock, &(ctrlrawsock[0]), r->connection->pool);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "proxy: FD: apr_os_sock_put failed");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ rv = apr_os_sock_put(&clientctrlsock, &(ctrlrawsock[1]), r->connection->pool);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "proxy: FD: apr_os_sock_put failed");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
{
int status;
/* const char *flush_method = worker->flusher ? worker->flusher : "flush"; */
/* There should really be a (documented) public API for this ! */
clientsock = ap_get_module_config(r->connection->conn_config, &core_module);
- rv = send_socket(r->pool, sock, clientsock);
+ rv = send_socket(r->pool, sock, clientsock, clientctrlsock);
if (rv != APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"proxy: FD: send_socket failed:");
return HTTP_INTERNAL_SERVER_ERROR;
}
+ strcat(headers_out, "\n");
+ wrlen = strlen(headers_out);
+ rv = apr_socket_send(ctrlsock, headers_out, &wrlen);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "proxy: FD: send headers failed");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ if (post_data) {
+ wrlen = strlen(post_data);
+ rv = apr_socket_send(ctrlsock, post_data, &wrlen);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "proxy: FD: send post failed");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+ apr_socket_shutdown(ctrlsock, APR_SHUTDOWN_READWRITE);
+ if (headers_out)
+ free(headers_out);
{
apr_socket_t *dummy;