aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorReilly Grant <grantr@vmware.com>2013-04-01 14:41:52 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-02 14:39:17 -0400
commit990454b5a48babde44a23c0f22bae5523f4fdf13 (patch)
treebf5f8ac3ed45b6a2e50225496d099c6d1059a56c /net
parent25fb6ca4ed9cad72f14f61629b68dc03c0d9713f (diff)
VSOCK: Handle changes to the VMCI context ID.
The VMCI context ID of a virtual machine may change at any time. There is a VMCI event which signals this but datagrams may be processed before this is handled. It is therefore necessary to be flexible about the destination context ID of any datagrams received. (It can be assumed to be correct because it is provided by the hypervisor.) The context ID on existing sockets should be updated to reflect how the hypervisor is currently referring to the system. Signed-off-by: Reilly Grant <grantr@vmware.com> Acked-by: Andy King <acking@vmware.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/vmw_vsock/af_vsock.c6
-rw-r--r--net/vmw_vsock/vmci_transport.c31
-rw-r--r--net/vmw_vsock/vsock_addr.c10
-rw-r--r--net/vmw_vsock/vsock_addr.h2
4 files changed, 23 insertions, 26 deletions
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index ca511c4f388a..d8079daf1bde 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -207,7 +207,7 @@ static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
207 struct vsock_sock *vsk; 207 struct vsock_sock *vsk;
208 208
209 list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table) 209 list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table)
210 if (vsock_addr_equals_addr_any(addr, &vsk->local_addr)) 210 if (addr->svm_port == vsk->local_addr.svm_port)
211 return sk_vsock(vsk); 211 return sk_vsock(vsk);
212 212
213 return NULL; 213 return NULL;
@@ -220,8 +220,8 @@ static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
220 220
221 list_for_each_entry(vsk, vsock_connected_sockets(src, dst), 221 list_for_each_entry(vsk, vsock_connected_sockets(src, dst),
222 connected_table) { 222 connected_table) {
223 if (vsock_addr_equals_addr(src, &vsk->remote_addr) 223 if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
224 && vsock_addr_equals_addr(dst, &vsk->local_addr)) { 224 dst->svm_port == vsk->local_addr.svm_port) {
225 return sk_vsock(vsk); 225 return sk_vsock(vsk);
226 } 226 }
227 } 227 }
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index a70ace83a153..1f6508e249ae 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -464,19 +464,16 @@ static struct sock *vmci_transport_get_pending(
464 struct vsock_sock *vlistener; 464 struct vsock_sock *vlistener;
465 struct vsock_sock *vpending; 465 struct vsock_sock *vpending;
466 struct sock *pending; 466 struct sock *pending;
467 struct sockaddr_vm src;
468
469 vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
467 470
468 vlistener = vsock_sk(listener); 471 vlistener = vsock_sk(listener);
469 472
470 list_for_each_entry(vpending, &vlistener->pending_links, 473 list_for_each_entry(vpending, &vlistener->pending_links,
471 pending_links) { 474 pending_links) {
472 struct sockaddr_vm src;
473 struct sockaddr_vm dst;
474
475 vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
476 vsock_addr_init(&dst, pkt->dg.dst.context, pkt->dst_port);
477
478 if (vsock_addr_equals_addr(&src, &vpending->remote_addr) && 475 if (vsock_addr_equals_addr(&src, &vpending->remote_addr) &&
479 vsock_addr_equals_addr(&dst, &vpending->local_addr)) { 476 pkt->dst_port == vpending->local_addr.svm_port) {
480 pending = sk_vsock(vpending); 477 pending = sk_vsock(vpending);
481 sock_hold(pending); 478 sock_hold(pending);
482 goto found; 479 goto found;
@@ -739,10 +736,15 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
739 */ 736 */
740 bh_lock_sock(sk); 737 bh_lock_sock(sk);
741 738
742 if (!sock_owned_by_user(sk) && sk->sk_state == SS_CONNECTED) 739 if (!sock_owned_by_user(sk)) {
743 vmci_trans(vsk)->notify_ops->handle_notify_pkt( 740 /* The local context ID may be out of date, update it. */
744 sk, pkt, true, &dst, &src, 741 vsk->local_addr.svm_cid = dst.svm_cid;
745 &bh_process_pkt); 742
743 if (sk->sk_state == SS_CONNECTED)
744 vmci_trans(vsk)->notify_ops->handle_notify_pkt(
745 sk, pkt, true, &dst, &src,
746 &bh_process_pkt);
747 }
746 748
747 bh_unlock_sock(sk); 749 bh_unlock_sock(sk);
748 750
@@ -902,6 +904,9 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work)
902 904
903 lock_sock(sk); 905 lock_sock(sk);
904 906
907 /* The local context ID may be out of date. */
908 vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
909
905 switch (sk->sk_state) { 910 switch (sk->sk_state) {
906 case SS_LISTEN: 911 case SS_LISTEN:
907 vmci_transport_recv_listen(sk, pkt); 912 vmci_transport_recv_listen(sk, pkt);
@@ -958,6 +963,10 @@ static int vmci_transport_recv_listen(struct sock *sk,
958 pending = vmci_transport_get_pending(sk, pkt); 963 pending = vmci_transport_get_pending(sk, pkt);
959 if (pending) { 964 if (pending) {
960 lock_sock(pending); 965 lock_sock(pending);
966
967 /* The local context ID may be out of date. */
968 vsock_sk(pending)->local_addr.svm_cid = pkt->dg.dst.context;
969
961 switch (pending->sk_state) { 970 switch (pending->sk_state) {
962 case SS_CONNECTING: 971 case SS_CONNECTING:
963 err = vmci_transport_recv_connecting_server(sk, 972 err = vmci_transport_recv_connecting_server(sk,
diff --git a/net/vmw_vsock/vsock_addr.c b/net/vmw_vsock/vsock_addr.c
index b7df1aea7c59..ec2611b4ea0e 100644
--- a/net/vmw_vsock/vsock_addr.c
+++ b/net/vmw_vsock/vsock_addr.c
@@ -64,16 +64,6 @@ bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
64} 64}
65EXPORT_SYMBOL_GPL(vsock_addr_equals_addr); 65EXPORT_SYMBOL_GPL(vsock_addr_equals_addr);
66 66
67bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
68 const struct sockaddr_vm *other)
69{
70 return (addr->svm_cid == VMADDR_CID_ANY ||
71 other->svm_cid == VMADDR_CID_ANY ||
72 addr->svm_cid == other->svm_cid) &&
73 addr->svm_port == other->svm_port;
74}
75EXPORT_SYMBOL_GPL(vsock_addr_equals_addr_any);
76
77int vsock_addr_cast(const struct sockaddr *addr, 67int vsock_addr_cast(const struct sockaddr *addr,
78 size_t len, struct sockaddr_vm **out_addr) 68 size_t len, struct sockaddr_vm **out_addr)
79{ 69{
diff --git a/net/vmw_vsock/vsock_addr.h b/net/vmw_vsock/vsock_addr.h
index cdfbcefdf843..9ccd5316eac0 100644
--- a/net/vmw_vsock/vsock_addr.h
+++ b/net/vmw_vsock/vsock_addr.h
@@ -24,8 +24,6 @@ bool vsock_addr_bound(const struct sockaddr_vm *addr);
24void vsock_addr_unbind(struct sockaddr_vm *addr); 24void vsock_addr_unbind(struct sockaddr_vm *addr);
25bool vsock_addr_equals_addr(const struct sockaddr_vm *addr, 25bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
26 const struct sockaddr_vm *other); 26 const struct sockaddr_vm *other);
27bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
28 const struct sockaddr_vm *other);
29int vsock_addr_cast(const struct sockaddr *addr, size_t len, 27int vsock_addr_cast(const struct sockaddr *addr, size_t len,
30 struct sockaddr_vm **out_addr); 28 struct sockaddr_vm **out_addr);
31 29