socket_wrapper: correctly handle connected dgram sockets
authorStefan Metzmacher <metze@samba.org>
Sun, 8 Mar 2009 16:19:50 +0000 (17:19 +0100)
committerStefan Metzmacher <metze@samba.org>
Sun, 8 Mar 2009 16:22:25 +0000 (17:22 +0100)
metze

lib/socket_wrapper/socket_wrapper.c

index 1f56a8358e3e0de36cdbee922c9648e632769132..b2d3a6b15d983b9597d9555b40f69000418dcd8d 100644 (file)
@@ -202,6 +202,7 @@ struct socket_info
        int bound;
        int bcast;
        int is_server;
+       int connected;
 
        char *path;
        char *tmp_path;
@@ -1487,6 +1488,7 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
        child_si->protocol = parent_si->protocol;
        child_si->bound = 1;
        child_si->is_server = 1;
+       child_si->connected = 1;
 
        child_si->peername_len = len;
        child_si->peername = sockaddr_dup(my_addr, len);
@@ -1674,7 +1676,14 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad
        if (ret == 0) {
                si->peername_len = addrlen;
                si->peername = sockaddr_dup(serv_addr, addrlen);
+               si->connected = 1;
+       }
+
+       if (si->type != SOCK_STREAM) {
+               return ret;
+       }
 
+       if (ret == 0) {
                swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
                swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
        } else {
@@ -1803,11 +1812,18 @@ _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct
        socklen_t un_addrlen = sizeof(un_addr);
        int ret;
        struct socket_info *si = find_socket_info(s);
+       struct sockaddr_storage ss;
+       socklen_t ss_len = sizeof(ss);
 
        if (!si) {
                return real_recvfrom(s, buf, len, flags, from, fromlen);
        }
 
+       if (!from) {
+               from = (struct sockaddr *)&ss;
+               fromlen = &ss_len;
+       }
+
        len = MIN(len, 1500);
 
        /* irix 6.4 forgets to null terminate the sun_path string :-( */
@@ -1838,6 +1854,16 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, con
                return real_sendto(s, buf, len, flags, to, tolen);
        }
 
+       if (si->connected) {
+               if (to) {
+                       errno = EISCONN;
+                       return -1;
+               }
+
+               to = si->peername;
+               tolen = si->peername_len;
+       }
+
        len = MIN(len, 1500);
 
        switch (si->type) {