Hello,

bert wrote:
So according to the output, all is well until it gets here:

status = listensocks[offset].accept_func((void *)&sock, &listensocks [offset], ptrans);

which seems to call receive_from_multiplexer to re-populate the sock structure... it seems somewhere within this function, the information about the original connection is not being passed over correctly.

You right, here. Looks like a sendmsg/recvmsg (SCM_RIGHTS) bug at
pass_socket()/pass_request() -> receive_from_multiplexer().
You can try my patch. It's working for me.
diff -Nru a/server/mpm/experimental/peruser/peruser.c b/server/mpm/experimental/peruser/peruser.c
--- a/server/mpm/experimental/peruser/peruser.c	2007-09-27 14:12:38.000000000 +0300
+++ b/server/mpm/experimental/peruser/peruser.c	2007-09-27 14:08:26.000000000 +0300
@@ -845,9 +845,10 @@
     int rv;
     struct msghdr msg;
     struct cmsghdr *cmsg;
+    apr_sockaddr_t *remote_addr;
     int sock_fd;
     char *body = "";
-    struct iovec iov[4];
+    struct iovec iov[5];
     apr_size_t len = 0;
     apr_size_t header_len = 0;
     apr_size_t body_len = 0;
@@ -867,6 +868,8 @@
     _DBG("passing request to another child.", 0);
 
     apr_os_sock_get(&sock_fd, thesock);
+    /* passing remote_addr too, see comments below */
+    apr_socket_addr_get(&remote_addr, APR_REMOTE, thesock);
     
     header_len = 0;
     body_len = 0;
@@ -875,15 +878,17 @@
     iov[0].iov_len  = sizeof(header_len);
     iov[1].iov_base = &body_len;
     iov[1].iov_len  = sizeof(body_len);
-    iov[2].iov_base = h.headers;
-    iov[2].iov_len  = 0;
-    iov[3].iov_base = body;
-    iov[3].iov_len  = body_len;
+    iov[2].iov_base = remote_addr;
+    iov[2].iov_len  = sizeof(*remote_addr);
+    iov[3].iov_base = h.headers;
+    iov[3].iov_len  = 0;
+    iov[4].iov_base = body;
+    iov[4].iov_len  = body_len;
 
     msg.msg_name    = NULL;
     msg.msg_namelen = 0;
     msg.msg_iov     = iov;
-    msg.msg_iovlen  = 4;
+    msg.msg_iovlen  = 5;
 
     cmsg = apr_palloc(pool, sizeof(*cmsg) + sizeof(sock_fd));
     cmsg->cmsg_len   = sizeof(*cmsg) + sizeof(sock_fd);
@@ -1082,9 +1087,10 @@
     int rv;
     struct msghdr msg;
     struct cmsghdr *cmsg;
+    apr_sockaddr_t *remote_addr;
     int sock_fd;
     char *body = "";
-    struct iovec iov[4];
+    struct iovec iov[5];
     conn_rec *c = r->connection;
     apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
     apr_bucket_brigade *body_bb = NULL;
@@ -1146,6 +1152,9 @@
     _DBG("Scanning is finished",0);
 
     apr_os_sock_get(&sock_fd, thesock);
+    /* looks like a bug while sending/receiving SCM_RIGHTS related to ipv6
+       workaround: send remote_addr structure too */
+    apr_socket_addr_get(&remote_addr, APR_REMOTE, thesock);
 
     h.p = r->pool;
 
@@ -1171,15 +1180,17 @@
     iov[0].iov_len  = sizeof(header_len);
     iov[1].iov_base = &body_len;
     iov[1].iov_len  = sizeof(body_len);
-    iov[2].iov_base = h.headers;
-    iov[2].iov_len  = strlen(h.headers) + 1;
-    iov[3].iov_base = body;
-    iov[3].iov_len  = body_len;
+    iov[2].iov_base = remote_addr;
+    iov[2].iov_len  = sizeof(*remote_addr);
+    iov[3].iov_base = h.headers;
+    iov[3].iov_len  = strlen(h.headers) + 1;
+    iov[4].iov_base = body;
+    iov[4].iov_len  = body_len;
 
     msg.msg_name    = NULL;
     msg.msg_namelen = 0;
     msg.msg_iov     = iov;
-    msg.msg_iovlen  = 4;
+    msg.msg_iovlen  = 5;
 
     cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sock_fd));
     cmsg->cmsg_len   = sizeof(*cmsg) + sizeof(sock_fd);
@@ -1233,10 +1244,12 @@
     char headers[HUGE_STRING_LEN] = "";
     char *body = "";
     apr_size_t header_len, body_len;
-    struct iovec iov[3];
+    struct iovec iov[4];
     int ret, fd_tmp;
     apr_os_sock_t ctrl_sock_fd;
     apr_os_sock_t trans_sock_fd;
+    apr_sockaddr_t remote_addr;
+    apr_os_sock_info_t sockinfo;
 
     /* -- bucket's, brigades and their allocators */
     apr_bucket_alloc_t *alloc = apr_bucket_alloc_create(ptrans);
@@ -1248,8 +1261,10 @@
     iov[0].iov_len  = sizeof(header_len);
     iov[1].iov_base = &body_len;
     iov[1].iov_len  = sizeof(body_len);
-    iov[2].iov_base = (char*)&buff;
-    iov[2].iov_len  = HUGE_STRING_LEN;
+    iov[2].iov_base = &remote_addr;
+    iov[2].iov_len  = sizeof(remote_addr);
+    iov[3].iov_base = (char*)&buff;
+    iov[3].iov_len  = HUGE_STRING_LEN;
 
     cmsg = apr_palloc(ptrans, sizeof(*cmsg) + sizeof(trans_sock_fd));
     cmsg->cmsg_len = sizeof(*cmsg) + sizeof(trans_sock_fd);
@@ -1257,7 +1272,7 @@
     msg.msg_name       = NULL;
     msg.msg_namelen    = 0;
     msg.msg_iov        = iov;
-    msg.msg_iovlen     = 3;
+    msg.msg_iovlen     = 4;
     msg.msg_control    = cmsg;
     msg.msg_controllen = cmsg->cmsg_len;
 
@@ -1273,7 +1288,17 @@
 
     /* -- extract socket from the cmsg -- */
     memcpy(&trans_sock_fd, CMSG_DATA(cmsg), sizeof(trans_sock_fd));
-    apr_os_sock_put((apr_socket_t **)trans_sock, &trans_sock_fd, ptrans);
+    /* here *trans_sock always == NULL (socket reset at got_fd), so
+       we can use apr_os_sock_make() instead of apr_os_sock_put() */
+    sockinfo.os_sock  = &trans_sock_fd;
+    sockinfo.local    = NULL;
+    sockinfo.remote   = (struct sockaddr *)&remote_addr.sa.sin;
+    sockinfo.family   = remote_addr.family;
+    sockinfo.type     = SOCK_STREAM;
+#ifdef APR_ENABLE_FOR_1_0
+    sockinfo.protocol = 0;
+#endif
+    apr_os_sock_make((apr_socket_t **)trans_sock, &sockinfo, ptrans);
     apr_os_sock_get(&fd_tmp, *trans_sock);
 
     _DBG("trans_sock=%ld fdx=%d sock_fd=%d",
_______________________________________________
Peruser mailing list
[email protected]
http://www.telana.com/mailman/listinfo/peruser

Reply via email to