ipv4: fix redirect handling
[linux-2.6.git] / net / tipc / socket.c
index e8254e8..adb2eff 100644 (file)
@@ -2,7 +2,7 @@
  * net/tipc/socket.c: TIPC socket API
  *
  * Copyright (c) 2001-2007, Ericsson AB
- * Copyright (c) 2004-2008, Wind River Systems
+ * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/net.h>
-#include <linux/socket.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <asm/string.h>
-#include <asm/atomic.h>
 #include <net/sock.h>
 
-#include <linux/tipc.h>
-#include <linux/tipc_config.h>
-#include <net/tipc/tipc_msg.h>
-#include <net/tipc/tipc_port.h>
-
 #include "core.h"
+#include "port.h"
 
 #define SS_LISTENING   -1      /* socket is listening */
 #define SS_READY       -2      /* socket is connectionless */
@@ -64,11 +49,15 @@ struct tipc_sock {
        struct sock sk;
        struct tipc_port *p;
        struct tipc_portid peer_name;
+       long conn_timeout;
 };
 
 #define tipc_sk(sk) ((struct tipc_sock *)(sk))
 #define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
 
+#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \
+                       (sock->state == SS_DISCONNECTING))
+
 static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
 static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
 static void wakeupdispatch(struct tipc_port *tport);
@@ -79,7 +68,7 @@ static const struct proto_ops msg_ops;
 
 static struct proto tipc_proto;
 
-static int sockets_enabled = 0;
+static int sockets_enabled;
 
 static atomic_t tipc_queue_size = ATOMIC_INIT(0);
 
@@ -177,6 +166,7 @@ static void reject_rx_queue(struct sock *sk)
  * @net: network namespace (must be default network)
  * @sock: pre-allocated socket structure
  * @protocol: protocol indicator (must be 0)
+ * @kern: caused by kernel or by userspace?
  *
  * This routine creates additional data structures used by the TIPC socket,
  * initializes them, and links them together.
@@ -184,7 +174,8 @@ static void reject_rx_queue(struct sock *sk)
  * Returns 0 on success, errno otherwise
  */
 
-static int tipc_create(struct net *net, struct socket *sock, int protocol)
+static int tipc_create(struct net *net, struct socket *sock, int protocol,
+                      int kern)
 {
        const struct proto_ops *ops;
        socket_state state;
@@ -193,7 +184,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
 
        /* Validate arguments */
 
-       if (net != &init_net)
+       if (!net_eq(net, &init_net))
                return -EAFNOSUPPORT;
 
        if (unlikely(protocol != 0))
@@ -238,9 +229,9 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
        sock->state = state;
 
        sock_init_data(sock, sk);
-       sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
        sk->sk_backlog_rcv = backlog_rcv;
        tipc_sk(sk)->p = tp_ptr;
+       tipc_sk(sk)->conn_timeout = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
 
        spin_unlock_bh(tp_ptr->lock);
 
@@ -250,7 +241,6 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
                        tipc_set_portunreliable(tp_ptr->ref, 1);
        }
 
-       atomic_inc(&tipc_user_count);
        return 0;
 }
 
@@ -299,7 +289,7 @@ static int release(struct socket *sock)
                if (buf == NULL)
                        break;
                atomic_dec(&tipc_queue_size);
-               if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
+               if (TIPC_SKB_CB(buf)->handle != 0)
                        buf_discard(buf);
                else {
                        if ((sock->state == SS_CONNECTING) ||
@@ -330,7 +320,6 @@ static int release(struct socket *sock)
        sock_put(sk);
        sock->sk = NULL;
 
-       atomic_dec(&tipc_user_count);
        return res;
 }
 
@@ -384,7 +373,7 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
  *
  * NOTE: This routine doesn't need to take the socket lock since it only
  *       accesses socket information that is unchanging (or which changes in
- *      a completely predictable manner).
+ *       a completely predictable manner).
  */
 
 static int get_name(struct socket *sock, struct sockaddr *uaddr,
@@ -393,6 +382,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
        struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
        struct tipc_sock *tsock = tipc_sk(sock->sk);
 
+       memset(addr, 0, sizeof(*addr));
        if (peer) {
                if ((sock->state != SS_CONNECTED) &&
                        ((peer != 2) || (sock->state != SS_DISCONNECTING)))
@@ -400,7 +390,8 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
                addr->addr.id.ref = tsock->peer_name.ref;
                addr->addr.id.node = tsock->peer_name.node;
        } else {
-               tipc_ownidentity(tsock->p->ref, &addr->addr.id);
+               addr->addr.id.ref = tsock->p->ref;
+               addr->addr.id.node = tipc_own_addr;
        }
 
        *uaddr_len = sizeof(*addr);
@@ -427,36 +418,55 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
  * to handle any preventable race conditions, so TIPC will do the same ...
  *
  * TIPC sets the returned events as follows:
- * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
- *    or if a connection-oriented socket is does not have an active connection
- *    (i.e. a read operation will not block).
- * b) POLLOUT is set except when a socket's connection has been terminated
- *    (i.e. a write operation will not block).
- * c) POLLHUP is set when a socket's connection has been terminated.
- *
- * IMPORTANT: The fact that a read or write operation will not block does NOT
- * imply that the operation will succeed!
+ *
+ * socket state                flags set
+ * ------------                ---------
+ * unconnected         no read flags
+ *                     no write flags
+ *
+ * connecting          POLLIN/POLLRDNORM if ACK/NACK in rx queue
+ *                     no write flags
+ *
+ * connected           POLLIN/POLLRDNORM if data in rx queue
+ *                     POLLOUT if port is not congested
+ *
+ * disconnecting       POLLIN/POLLRDNORM/POLLHUP
+ *                     no write flags
+ *
+ * listening           POLLIN if SYN in rx queue
+ *                     no write flags
+ *
+ * ready               POLLIN/POLLRDNORM if data in rx queue
+ * [connectionless]    POLLOUT (since port cannot be congested)
+ *
+ * IMPORTANT: The fact that a read or write operation is indicated does NOT
+ * imply that the operation will succeed, merely that it should be performed
+ * and will not block.
  */
 
 static unsigned int poll(struct file *file, struct socket *sock,
                         poll_table *wait)
 {
        struct sock *sk = sock->sk;
-       u32 mask;
+       u32 mask = 0;
 
-       poll_wait(file, sk->sk_sleep, wait);
-
-       if (!skb_queue_empty(&sk->sk_receive_queue) ||
-           (sock->state == SS_UNCONNECTED) ||
-           (sock->state == SS_DISCONNECTING))
-               mask = (POLLRDNORM | POLLIN);
-       else
-               mask = 0;
+       poll_wait(file, sk_sleep(sk), wait);
 
-       if (sock->state == SS_DISCONNECTING)
-               mask |= POLLHUP;
-       else
-               mask |= POLLOUT;
+       switch ((int)sock->state) {
+       case SS_READY:
+       case SS_CONNECTED:
+               if (!tipc_sk_port(sk)->congested)
+                       mask |= POLLOUT;
+               /* fall thru' */
+       case SS_CONNECTING:
+       case SS_LISTENING:
+               if (!skb_queue_empty(&sk->sk_receive_queue))
+                       mask |= (POLLIN | POLLRDNORM);
+               break;
+       case SS_DISCONNECTING:
+               mask = (POLLIN | POLLRDNORM | POLLHUP);
+               break;
+       }
 
        return mask;
 }
@@ -483,6 +493,8 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
        if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
                return -EACCES;
 
+       if (!m->msg_iovlen || (m->msg_iov[0].iov_len < sizeof(hdr)))
+               return -EMSGSIZE;
        if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
                return -EFAULT;
        if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN)))
@@ -520,6 +532,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
        if (unlikely((m->msg_namelen < sizeof(*dest)) ||
                     (dest->family != AF_TIPC)))
                return -EINVAL;
+       if ((total_len > TIPC_MAX_USER_MSG_SIZE) ||
+           (m->msg_iovlen > (unsigned)INT_MAX))
+               return -EMSGSIZE;
 
        if (iocb)
                lock_sock(sk);
@@ -551,37 +566,38 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
 
        do {
                if (dest->addrtype == TIPC_ADDR_NAME) {
-                       if ((res = dest_name_check(dest, m)))
+                       res = dest_name_check(dest, m);
+                       if (res)
                                break;
                        res = tipc_send2name(tport->ref,
                                             &dest->addr.name.name,
                                             dest->addr.name.domain,
                                             m->msg_iovlen,
-                                            m->msg_iov);
-               }
-               else if (dest->addrtype == TIPC_ADDR_ID) {
+                                            m->msg_iov,
+                                            total_len);
+               } else if (dest->addrtype == TIPC_ADDR_ID) {
                        res = tipc_send2port(tport->ref,
                                             &dest->addr.id,
                                             m->msg_iovlen,
-                                            m->msg_iov);
-               }
-               else if (dest->addrtype == TIPC_ADDR_MCAST) {
+                                            m->msg_iov,
+                                            total_len);
+               } else if (dest->addrtype == TIPC_ADDR_MCAST) {
                        if (needs_conn) {
                                res = -EOPNOTSUPP;
                                break;
                        }
-                       if ((res = dest_name_check(dest, m)))
+                       res = dest_name_check(dest, m);
+                       if (res)
                                break;
                        res = tipc_multicast(tport->ref,
                                             &dest->addr.nameseq,
-                                            0,
                                             m->msg_iovlen,
-                                            m->msg_iov);
+                                            m->msg_iov,
+                                            total_len);
                }
                if (likely(res != -ELINKCONG)) {
-                       if (needs_conn && (res >= 0)) {
+                       if (needs_conn && (res >= 0))
                                sock->state = SS_CONNECTING;
-                       }
                        break;
                }
                if (m->msg_flags & MSG_DONTWAIT) {
@@ -589,7 +605,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
                        break;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                                               !tport->congested);
                lock_sock(sk);
                if (res)
@@ -627,6 +643,10 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
        if (unlikely(dest))
                return send_msg(iocb, sock, m, total_len);
 
+       if ((total_len > TIPC_MAX_USER_MSG_SIZE) ||
+           (m->msg_iovlen > (unsigned)INT_MAX))
+               return -EMSGSIZE;
+
        if (iocb)
                lock_sock(sk);
 
@@ -639,16 +659,16 @@ static int send_packet(struct kiocb *iocb, struct socket *sock,
                        break;
                }
 
-               res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov);
-               if (likely(res != -ELINKCONG)) {
+               res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov,
+                               total_len);
+               if (likely(res != -ELINKCONG))
                        break;
-               }
                if (m->msg_flags & MSG_DONTWAIT) {
                        res = -EWOULDBLOCK;
                        break;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                        (!tport->congested || !tport->connected));
                lock_sock(sk);
                if (res)
@@ -711,6 +731,12 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
                goto exit;
        }
 
+       if ((total_len > (unsigned)INT_MAX) ||
+           (m->msg_iovlen > (unsigned)INT_MAX)) {
+               res = -EMSGSIZE;
+               goto exit;
+       }
+
        /*
         * Send each iovec entry using one or more messages
         *
@@ -741,7 +767,8 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
                                bytes_to_send = curr_left;
                        my_iov.iov_base = curr_start;
                        my_iov.iov_len = bytes_to_send;
-                       if ((res = send_packet(NULL, sock, &my_msg, 0)) < 0) {
+                       res = send_packet(NULL, sock, &my_msg, bytes_to_send);
+                       if (res < 0) {
                                if (bytes_sent)
                                        res = bytes_sent;
                                goto exit;
@@ -801,8 +828,8 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
                addr->addrtype = TIPC_ADDR_ID;
                addr->addr.id.ref = msg_origport(msg);
                addr->addr.id.node = msg_orignode(msg);
-               addr->addr.name.domain = 0;     /* could leave uninitialized */
-               addr->scope = 0;                /* could leave uninitialized */
+               addr->addr.name.domain = 0;     /* could leave uninitialized */
+               addr->scope = 0;                /* could leave uninitialized */
                m->msg_namelen = sizeof(struct sockaddr_tipc);
        }
 }
@@ -836,12 +863,15 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
        if (unlikely(err)) {
                anc_data[0] = err;
                anc_data[1] = msg_data_sz(msg);
-               if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data)))
-                       return res;
-               if (anc_data[1] &&
-                   (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1],
-                                   msg_data(msg))))
+               res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data);
+               if (res)
                        return res;
+               if (anc_data[1]) {
+                       res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1],
+                                      msg_data(msg));
+                       if (res)
+                               return res;
+               }
        }
 
        /* Optionally capture message destination object */
@@ -869,9 +899,11 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
        default:
                has_name = 0;
        }
-       if (has_name &&
-           (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data)))
-               return res;
+       if (has_name) {
+               res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data);
+               if (res)
+                       return res;
+       }
 
        return 0;
 }
@@ -896,15 +928,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
        struct tipc_port *tport = tipc_sk_port(sk);
        struct sk_buff *buf;
        struct tipc_msg *msg;
+       long timeout;
        unsigned int sz;
        u32 err;
        int res;
 
        /* Catch invalid receive requests */
 
-       if (m->msg_iovlen != 1)
-               return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
-
        if (unlikely(!buf_len))
                return -EINVAL;
 
@@ -915,6 +945,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
                goto exit;
        }
 
+       timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 restart:
 
        /* Look for a message in receive queue; wait if necessary */
@@ -924,17 +955,15 @@ restart:
                        res = -ENOTCONN;
                        goto exit;
                }
-               if (flags & MSG_DONTWAIT) {
-                       res = -EWOULDBLOCK;
+               if (timeout <= 0L) {
+                       res = timeout ? timeout : -EWOULDBLOCK;
                        goto exit;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
-                       (!skb_queue_empty(&sk->sk_receive_queue) ||
-                        (sock->state == SS_DISCONNECTING)));
+               timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
+                                                          tipc_rx_ready(sock),
+                                                          timeout);
                lock_sock(sk);
-               if (res)
-                       goto exit;
        }
 
        /* Look at first message in receive queue */
@@ -976,11 +1005,10 @@ restart:
                        sz = buf_len;
                        m->msg_flags |= MSG_TRUNC;
                }
-               if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
-                                         sz))) {
-                       res = -EFAULT;
+               res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
+                                             m->msg_iov, sz);
+               if (res)
                        goto exit;
-               }
                res = sz;
        } else {
                if ((sock->state == SS_READY) ||
@@ -1023,20 +1051,15 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
        struct tipc_port *tport = tipc_sk_port(sk);
        struct sk_buff *buf;
        struct tipc_msg *msg;
+       long timeout;
        unsigned int sz;
-       int sz_to_copy;
+       int sz_to_copy, target, needed;
        int sz_copied = 0;
-       int needed;
-       char __user *crs = m->msg_iov->iov_base;
-       unsigned char *buf_crs;
        u32 err;
        int res = 0;
 
        /* Catch invalid receive attempts */
 
-       if (m->msg_iovlen != 1)
-               return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
-
        if (unlikely(!buf_len))
                return -EINVAL;
 
@@ -1048,6 +1071,8 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
                goto exit;
        }
 
+       target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
+       timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 restart:
 
        /* Look for a message in receive queue; wait if necessary */
@@ -1057,17 +1082,15 @@ restart:
                        res = -ENOTCONN;
                        goto exit;
                }
-               if (flags & MSG_DONTWAIT) {
-                       res = -EWOULDBLOCK;
+               if (timeout <= 0L) {
+                       res = timeout ? timeout : -EWOULDBLOCK;
                        goto exit;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
-                       (!skb_queue_empty(&sk->sk_receive_queue) ||
-                        (sock->state == SS_DISCONNECTING)));
+               timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
+                                                          tipc_rx_ready(sock),
+                                                          timeout);
                lock_sock(sk);
-               if (res)
-                       goto exit;
        }
 
        /* Look at first message in receive queue */
@@ -1096,24 +1119,25 @@ restart:
        /* Capture message data (if valid) & compute return value (always) */
 
        if (!err) {
-               buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
-               sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
+               u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
 
+               sz -= offset;
                needed = (buf_len - sz_copied);
                sz_to_copy = (sz <= needed) ? sz : needed;
-               if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
-                       res = -EFAULT;
+
+               res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
+                                             m->msg_iov, sz_to_copy);
+               if (res)
                        goto exit;
-               }
+
                sz_copied += sz_to_copy;
 
                if (sz_to_copy < sz) {
                        if (!(flags & MSG_PEEK))
-                               TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
+                               TIPC_SKB_CB(buf)->handle =
+                               (void *)(unsigned long)(offset + sz_to_copy);
                        goto exit;
                }
-
-               crs += sz_to_copy;
        } else {
                if (sz_copied != 0)
                        goto exit; /* can't add error msg to valid data */
@@ -1134,13 +1158,11 @@ restart:
 
        /* Loop around if more data is required */
 
-       if ((sz_copied < buf_len)    /* didn't get all requested data */
-           && (!skb_queue_empty(&sk->sk_receive_queue) ||
-               (flags & MSG_WAITALL))
-                                    /* ... and more is ready or required */
-           && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */
-           && (!err)                /* ... and haven't reached a FIN */
-           )
+       if ((sz_copied < buf_len) &&    /* didn't get all requested data */
+           (!skb_queue_empty(&sk->sk_receive_queue) ||
+           (sz_copied < target)) &&    /* and more is ready or required */
+           (!(flags & MSG_PEEK)) &&    /* and aren't just peeking at data */
+           (!err))                     /* and haven't reached a FIN */
                goto restart;
 
 exit:
@@ -1174,7 +1196,7 @@ static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
        if (msg_connected(msg))
                threshold *= 4;
 
-       return (queue_size >= threshold);
+       return queue_size >= threshold;
 }
 
 /**
@@ -1205,42 +1227,25 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
         */
 
        if (sock->state == SS_READY) {
-               if (msg_connected(msg)) {
-                       msg_dbg(msg, "dispatch filter 1\n");
+               if (msg_connected(msg))
                        return TIPC_ERR_NO_PORT;
-               }
        } else {
-               if (msg_mcast(msg)) {
-                       msg_dbg(msg, "dispatch filter 2\n");
+               if (msg_mcast(msg))
                        return TIPC_ERR_NO_PORT;
-               }
                if (sock->state == SS_CONNECTED) {
-                       if (!msg_connected(msg)) {
-                               msg_dbg(msg, "dispatch filter 3\n");
+                       if (!msg_connected(msg))
                                return TIPC_ERR_NO_PORT;
-                       }
-               }
-               else if (sock->state == SS_CONNECTING) {
-                       if (!msg_connected(msg) && (msg_errcode(msg) == 0)) {
-                               msg_dbg(msg, "dispatch filter 4\n");
+               } else if (sock->state == SS_CONNECTING) {
+                       if (!msg_connected(msg) && (msg_errcode(msg) == 0))
                                return TIPC_ERR_NO_PORT;
-                       }
-               }
-               else if (sock->state == SS_LISTENING) {
-                       if (msg_connected(msg) || msg_errcode(msg)) {
-                               msg_dbg(msg, "dispatch filter 5\n");
+               } else if (sock->state == SS_LISTENING) {
+                       if (msg_connected(msg) || msg_errcode(msg))
                                return TIPC_ERR_NO_PORT;
-                       }
-               }
-               else if (sock->state == SS_DISCONNECTING) {
-                       msg_dbg(msg, "dispatch filter 6\n");
+               } else if (sock->state == SS_DISCONNECTING) {
                        return TIPC_ERR_NO_PORT;
-               }
-               else /* (sock->state == SS_UNCONNECTED) */ {
-                       if (msg_connected(msg) || msg_errcode(msg)) {
-                               msg_dbg(msg, "dispatch filter 7\n");
+               } else /* (sock->state == SS_UNCONNECTED) */ {
+                       if (msg_connected(msg) || msg_errcode(msg))
                                return TIPC_ERR_NO_PORT;
-                       }
                }
        }
 
@@ -1259,8 +1264,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
 
        /* Enqueue message (finally!) */
 
-       msg_dbg(msg, "<DISP<: ");
-       TIPC_SKB_CB(buf)->handle = msg_data(msg);
+       TIPC_SKB_CB(buf)->handle = 0;
        atomic_inc(&tipc_queue_size);
        __skb_queue_tail(&sk->sk_receive_queue, buf);
 
@@ -1271,8 +1275,8 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
                tipc_disconnect_port(tipc_sk_port(sk));
        }
 
-       if (waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
+       if (waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible(sk_sleep(sk));
        return TIPC_OK;
 }
 
@@ -1322,8 +1326,10 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
        if (!sock_owned_by_user(sk)) {
                res = filter_rcv(sk, buf);
        } else {
-               sk_add_backlog(sk, buf);
-               res = TIPC_OK;
+               if (sk_add_backlog(sk, buf))
+                       res = TIPC_ERR_OVERLOAD;
+               else
+                       res = TIPC_OK;
        }
        bh_unlock_sock(sk);
 
@@ -1341,8 +1347,8 @@ static void wakeupdispatch(struct tipc_port *tport)
 {
        struct sock *sk = (struct sock *)tport->usr_handle;
 
-       if (waitqueue_active(sk->sk_sleep))
-               wake_up_interruptible(sk->sk_sleep);
+       if (waitqueue_active(sk_sleep(sk)))
+               wake_up_interruptible(sk_sleep(sk));
 }
 
 /**
@@ -1363,6 +1369,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
        struct msghdr m = {NULL,};
        struct sk_buff *buf;
        struct tipc_msg *msg;
+       long timeout;
        int res;
 
        lock_sock(sk);
@@ -1377,7 +1384,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
        /* For now, TIPC does not support the non-blocking form of connect() */
 
        if (flags & O_NONBLOCK) {
-               res = -EWOULDBLOCK;
+               res = -EOPNOTSUPP;
                goto exit;
        }
 
@@ -1417,17 +1424,17 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
        m.msg_name = dest;
        m.msg_namelen = destlen;
        res = send_msg(NULL, sock, &m, 0);
-       if (res < 0) {
+       if (res < 0)
                goto exit;
-       }
 
        /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
 
+       timeout = tipc_sk(sk)->conn_timeout;
        release_sock(sk);
-       res = wait_event_interruptible_timeout(*sk->sk_sleep,
+       res = wait_event_interruptible_timeout(*sk_sleep(sk),
                        (!skb_queue_empty(&sk->sk_receive_queue) ||
                        (sock->state != SS_CONNECTING)),
-                       sk->sk_rcvtimeo);
+                       timeout ? timeout : MAX_SCHEDULE_TIMEOUT);
        lock_sock(sk);
 
        if (res > 0) {
@@ -1440,11 +1447,10 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
                                        advance_rx_queue(sk);
                        }
                } else {
-                       if (sock->state == SS_CONNECTED) {
+                       if (sock->state == SS_CONNECTED)
                                res = -EISCONN;
-                       } else {
+                       else
                                res = -ECONNREFUSED;
-                       }
                }
        } else {
                if (res == 0)
@@ -1519,7 +1525,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
                        goto exit;
                }
                release_sock(sk);
-               res = wait_event_interruptible(*sk->sk_sleep,
+               res = wait_event_interruptible(*sk_sleep(sk),
                                (!skb_queue_empty(&sk->sk_receive_queue)));
                lock_sock(sk);
                if (res)
@@ -1528,7 +1534,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
 
        buf = skb_peek(&sk->sk_receive_queue);
 
-       res = tipc_create(sock_net(sock->sk), new_sock, 0);
+       res = tipc_create(sock_net(sock->sk), new_sock, 0, 0);
        if (!res) {
                struct sock *new_sk = new_sock->sk;
                struct tipc_sock *new_tsock = tipc_sk(new_sk);
@@ -1563,7 +1569,6 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
                 * Respond to 'SYN+' by queuing it on new socket.
                 */
 
-               msg_dbg(msg,"<ACC<: ");
                if (!msg_data_sz(msg)) {
                        struct msghdr m = {NULL,};
 
@@ -1611,7 +1616,7 @@ restart:
                buf = __skb_dequeue(&sk->sk_receive_queue);
                if (buf) {
                        atomic_dec(&tipc_queue_size);
-                       if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
+                       if (TIPC_SKB_CB(buf)->handle != 0) {
                                buf_discard(buf);
                                goto restart;
                        }
@@ -1630,8 +1635,8 @@ restart:
                /* Discard any unreceived messages; wake up sleeping tasks */
 
                discard_rx_queue(sk);
-               if (waitqueue_active(sk->sk_sleep))
-                       wake_up_interruptible(sk->sk_sleep);
+               if (waitqueue_active(sk_sleep(sk)))
+                       wake_up_interruptible(sk_sleep(sk));
                res = 0;
                break;
 
@@ -1658,7 +1663,7 @@ restart:
  */
 
 static int setsockopt(struct socket *sock,
-                     int lvl, int opt, char __user *ov, int ol)
+                     int lvl, int opt, char __user *ov, unsigned int ol)
 {
        struct sock *sk = sock->sk;
        struct tipc_port *tport = tipc_sk_port(sk);
@@ -1671,7 +1676,8 @@ static int setsockopt(struct socket *sock,
                return -ENOPROTOOPT;
        if (ol < sizeof(value))
                return -EINVAL;
-       if ((res = get_user(value, (u32 __user *)ov)))
+       res = get_user(value, (u32 __user *)ov);
+       if (res)
                return res;
 
        lock_sock(sk);
@@ -1690,7 +1696,7 @@ static int setsockopt(struct socket *sock,
                res = tipc_set_portunreturnable(tport->ref, value);
                break;
        case TIPC_CONN_TIMEOUT:
-               sk->sk_rcvtimeo = msecs_to_jiffies(value);
+               tipc_sk(sk)->conn_timeout = msecs_to_jiffies(value);
                /* no need to set "res", since already 0 at this point */
                break;
        default:
@@ -1729,7 +1735,8 @@ static int getsockopt(struct socket *sock,
                return put_user(0, ol);
        if (lvl != SOL_TIPC)
                return -ENOPROTOOPT;
-       if ((res = get_user(len, ol)))
+       res = get_user(len, ol);
+       if (res)
                return res;
 
        lock_sock(sk);
@@ -1745,13 +1752,13 @@ static int getsockopt(struct socket *sock,
                res = tipc_portunreturnable(tport->ref, &value);
                break;
        case TIPC_CONN_TIMEOUT:
-               value = jiffies_to_msecs(sk->sk_rcvtimeo);
+               value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout);
                /* no need to set "res", since already 0 at this point */
                break;
-        case TIPC_NODE_RECVQ_DEPTH:
+       case TIPC_NODE_RECVQ_DEPTH:
                value = (u32)atomic_read(&tipc_queue_size);
                break;
-        case TIPC_SOCK_RECVQ_DEPTH:
+       case TIPC_SOCK_RECVQ_DEPTH:
                value = skb_queue_len(&sk->sk_receive_queue);
                break;
        default:
@@ -1760,20 +1767,16 @@ static int getsockopt(struct socket *sock,
 
        release_sock(sk);
 
-       if (res) {
-               /* "get" failed */
-       }
-       else if (len < sizeof(value)) {
-               res = -EINVAL;
-       }
-       else if (copy_to_user(ov, &value, sizeof(value))) {
-               res = -EFAULT;
-       }
-       else {
-               res = put_user(sizeof(value), ol);
-       }
+       if (res)
+               return res;     /* "get" failed */
 
-       return res;
+       if (len < sizeof(value))
+               return -EINVAL;
+
+       if (copy_to_user(ov, &value, sizeof(value)))
+               return -EFAULT;
+
+       return put_user(sizeof(value), ol);
 }
 
 /**
@@ -1781,7 +1784,7 @@ static int getsockopt(struct socket *sock,
  */
 
 static const struct proto_ops msg_ops = {
-       .owner          = THIS_MODULE,
+       .owner          = THIS_MODULE,
        .family         = AF_TIPC,
        .release        = release,
        .bind           = bind,
@@ -1802,7 +1805,7 @@ static const struct proto_ops msg_ops = {
 };
 
 static const struct proto_ops packet_ops = {
-       .owner          = THIS_MODULE,
+       .owner          = THIS_MODULE,
        .family         = AF_TIPC,
        .release        = release,
        .bind           = bind,
@@ -1823,7 +1826,7 @@ static const struct proto_ops packet_ops = {
 };
 
 static const struct proto_ops stream_ops = {
-       .owner          = THIS_MODULE,
+       .owner          = THIS_MODULE,
        .family         = AF_TIPC,
        .release        = release,
        .bind           = bind,
@@ -1844,7 +1847,7 @@ static const struct proto_ops stream_ops = {
 };
 
 static const struct net_proto_family tipc_family_ops = {
-       .owner          = THIS_MODULE,
+       .owner          = THIS_MODULE,
        .family         = AF_TIPC,
        .create         = tipc_create
 };