summaryrefslogtreecommitdiffstats
path: root/net/tipc/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r--net/tipc/socket.c62
1 files changed, 33 insertions, 29 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 230f9ca2ad6b..1848693ebb82 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2,7 +2,7 @@
* net/tipc/socket.c: TIPC socket API
*
* Copyright (c) 2001-2007, Ericsson AB
- * Copyright (c) 2004-2007, Wind River Systems
+ * Copyright (c) 2004-2008, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@
struct tipc_sock {
struct sock sk;
struct tipc_port *p;
+ struct tipc_portid peer_name;
};
#define tipc_sk(sk) ((struct tipc_sock *)(sk))
@@ -188,7 +189,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
const struct proto_ops *ops;
socket_state state;
struct sock *sk;
- u32 portref;
+ struct tipc_port *tp_ptr;
/* Validate arguments */
@@ -224,9 +225,9 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
/* Allocate TIPC port for socket to use */
- portref = tipc_createport_raw(sk, &dispatch, &wakeupdispatch,
- TIPC_LOW_IMPORTANCE);
- if (unlikely(portref == 0)) {
+ tp_ptr = tipc_createport_raw(sk, &dispatch, &wakeupdispatch,
+ TIPC_LOW_IMPORTANCE);
+ if (unlikely(!tp_ptr)) {
sk_free(sk);
return -ENOMEM;
}
@@ -239,12 +240,14 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol)
sock_init_data(sock, sk);
sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT);
sk->sk_backlog_rcv = backlog_rcv;
- tipc_sk(sk)->p = tipc_get_port(portref);
+ tipc_sk(sk)->p = tp_ptr;
+
+ spin_unlock_bh(tp_ptr->lock);
if (sock->state == SS_READY) {
- tipc_set_portunreturnable(portref, 1);
+ tipc_set_portunreturnable(tp_ptr->ref, 1);
if (sock->type == SOCK_DGRAM)
- tipc_set_portunreliable(portref, 1);
+ tipc_set_portunreliable(tp_ptr->ref, 1);
}
atomic_inc(&tipc_user_count);
@@ -375,27 +378,29 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
* @sock: socket structure
* @uaddr: area for returned socket address
* @uaddr_len: area for returned length of socket address
- * @peer: 0 to obtain socket name, 1 to obtain peer socket name
+ * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID
*
* Returns 0 on success, errno otherwise
*
- * NOTE: This routine doesn't need to take the socket lock since it doesn't
- * access any non-constant socket information.
+ * 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).
*/
static int get_name(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
- u32 portref = tipc_sk_port(sock->sk)->ref;
- u32 res;
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
if (peer) {
- res = tipc_peer(portref, &addr->addr.id);
- if (res)
- return res;
+ if ((sock->state != SS_CONNECTED) &&
+ ((peer != 2) || (sock->state != SS_DISCONNECTING)))
+ return -ENOTCONN;
+ addr->addr.id.ref = tsock->peer_name.ref;
+ addr->addr.id.node = tsock->peer_name.node;
} else {
- tipc_ownidentity(portref, &addr->addr.id);
+ tipc_ownidentity(tsock->p->ref, &addr->addr.id);
}
*uaddr_len = sizeof(*addr);
@@ -764,18 +769,17 @@ exit:
static int auto_connect(struct socket *sock, struct tipc_msg *msg)
{
- struct tipc_port *tport = tipc_sk_port(sock->sk);
- struct tipc_portid peer;
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
if (msg_errcode(msg)) {
sock->state = SS_DISCONNECTING;
return -ECONNREFUSED;
}
- peer.ref = msg_origport(msg);
- peer.node = msg_orignode(msg);
- tipc_connect2port(tport->ref, &peer);
- tipc_set_portimportance(tport->ref, msg_importance(msg));
+ tsock->peer_name.ref = msg_origport(msg);
+ tsock->peer_name.node = msg_orignode(msg);
+ tipc_connect2port(tsock->p->ref, &tsock->peer_name);
+ tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
sock->state = SS_CONNECTED;
return 0;
}
@@ -1131,7 +1135,7 @@ restart:
/* Loop around if more data is required */
if ((sz_copied < buf_len) /* didn't get all requested data */
- && (!skb_queue_empty(&sock->sk->sk_receive_queue) ||
+ && (!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 */
@@ -1527,9 +1531,9 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
res = tipc_create(sock_net(sock->sk), new_sock, 0);
if (!res) {
struct sock *new_sk = new_sock->sk;
- struct tipc_port *new_tport = tipc_sk_port(new_sk);
+ struct tipc_sock *new_tsock = tipc_sk(new_sk);
+ struct tipc_port *new_tport = new_tsock->p;
u32 new_ref = new_tport->ref;
- struct tipc_portid id;
struct tipc_msg *msg = buf_msg(buf);
lock_sock(new_sk);
@@ -1543,9 +1547,9 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
/* Connect new socket to it's peer */
- id.ref = msg_origport(msg);
- id.node = msg_orignode(msg);
- tipc_connect2port(new_ref, &id);
+ new_tsock->peer_name.ref = msg_origport(msg);
+ new_tsock->peer_name.node = msg_orignode(msg);
+ tipc_connect2port(new_ref, &new_tsock->peer_name);
new_sock->state = SS_CONNECTED;
tipc_set_portimportance(new_ref, msg_importance(msg));