Blame view

net/tipc/socket.c 71.8 KB
b97bf3fd8   Per Liden   [TIPC] Initial merge
1
  /*
02c00c2ab   Jon Paul Maloy   tipc: fix potenti...
2
   * net/tipc/socket.c: TIPC socket API
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
3
   *
51b9a31c4   Jon Paul Maloy   tipc: eliminate o...
4
   * Copyright (c) 2001-2007, 2012-2016, Ericsson AB
c5fa7b3cf   Ying Xue   tipc: introduce n...
5
   * Copyright (c) 2004-2008, 2010-2013, Wind River Systems
b97bf3fd8   Per Liden   [TIPC] Initial merge
6
7
   * All rights reserved.
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
8
   * Redistribution and use in source and binary forms, with or without
b97bf3fd8   Per Liden   [TIPC] Initial merge
9
10
   * modification, are permitted provided that the following conditions are met:
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
11
12
13
14
15
16
17
18
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the names of the copyright holders nor the names of its
   *    contributors may be used to endorse or promote products derived from
   *    this software without specific prior written permission.
b97bf3fd8   Per Liden   [TIPC] Initial merge
19
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
b97bf3fd8   Per Liden   [TIPC] Initial merge
34
35
   * POSSIBILITY OF SUCH DAMAGE.
   */
07f6c4bc0   Ying Xue   tipc: convert tip...
36
  #include <linux/rhashtable.h>
b97bf3fd8   Per Liden   [TIPC] Initial merge
37
  #include "core.h"
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
38
  #include "name_table.h"
78acb1f9b   Erik Hugne   tipc: add ioctl t...
39
  #include "node.h"
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
40
  #include "link.h"
c637c1035   Jon Paul Maloy   tipc: resolve rac...
41
  #include "name_distr.h"
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
42
  #include "socket.h"
a6bf70f79   Jon Paul Maloy   tipc: simplify in...
43
  #include "bcast.h"
49cc66eae   Richard Alpe   tipc: move netlin...
44
  #include "netlink.h"
2cf8aa19f   Erik Hugne   tipc: use standar...
45

07f6c4bc0   Ying Xue   tipc: convert tip...
46
47
  #define SS_LISTENING		-1	/* socket is listening */
  #define SS_READY		-2	/* socket is connectionless */
b97bf3fd8   Per Liden   [TIPC] Initial merge
48

07f6c4bc0   Ying Xue   tipc: convert tip...
49
  #define CONN_TIMEOUT_DEFAULT	8000	/* default connect timeout = 8s */
2f55c4378   Ying Xue   tipc: remove unne...
50
  #define CONN_PROBING_INTERVAL	msecs_to_jiffies(3600000)  /* [ms] => 1 h */
07f6c4bc0   Ying Xue   tipc: convert tip...
51
52
53
54
55
  #define TIPC_FWD_MSG		1
  #define TIPC_CONN_OK		0
  #define TIPC_CONN_PROBING	1
  #define TIPC_MAX_PORT		0xffffffff
  #define TIPC_MIN_PORT		1
301bae56f   Jon Paul Maloy   tipc: merge struc...
56
57
58
59
60
61
62
63
64
  
  /**
   * struct tipc_sock - TIPC socket structure
   * @sk: socket - interacts with 'port' and with user via the socket API
   * @connected: non-zero if port is currently connected to a peer port
   * @conn_type: TIPC type used when connection was established
   * @conn_instance: TIPC instance used when connection was established
   * @published: non-zero if port has one or more associated names
   * @max_pkt: maximum packet size "hint" used when building messages sent by port
07f6c4bc0   Ying Xue   tipc: convert tip...
65
   * @portid: unique port identity in TIPC socket hash table
301bae56f   Jon Paul Maloy   tipc: merge struc...
66
67
68
69
70
   * @phdr: preformatted message header used when sending messages
   * @port_list: adjacent ports in TIPC's global list of ports
   * @publications: list of publications for port
   * @pub_count: total # of publications port has made during its lifetime
   * @probing_state:
2f55c4378   Ying Xue   tipc: remove unne...
71
   * @probing_intv:
301bae56f   Jon Paul Maloy   tipc: merge struc...
72
73
74
75
76
   * @conn_timeout: the time we can wait for an unresponded setup request
   * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue
   * @link_cong: non-zero if owner must sleep because of link congestion
   * @sent_unacked: # messages sent by socket, and not yet acked by peer
   * @rcv_unacked: # messages read by user, but not yet acked back to peer
f2f8036e3   Erik Hugne   tipc: add support...
77
   * @remote: 'connected' peer for dgram/rdm
07f6c4bc0   Ying Xue   tipc: convert tip...
78
79
   * @node: hash table node
   * @rcu: rcu struct for tipc_sock
301bae56f   Jon Paul Maloy   tipc: merge struc...
80
81
82
83
84
85
86
87
   */
  struct tipc_sock {
  	struct sock sk;
  	int connected;
  	u32 conn_type;
  	u32 conn_instance;
  	int published;
  	u32 max_pkt;
07f6c4bc0   Ying Xue   tipc: convert tip...
88
  	u32 portid;
301bae56f   Jon Paul Maloy   tipc: merge struc...
89
90
91
92
93
  	struct tipc_msg phdr;
  	struct list_head sock_list;
  	struct list_head publications;
  	u32 pub_count;
  	u32 probing_state;
2f55c4378   Ying Xue   tipc: remove unne...
94
  	unsigned long probing_intv;
301bae56f   Jon Paul Maloy   tipc: merge struc...
95
96
97
  	uint conn_timeout;
  	atomic_t dupl_rcvcnt;
  	bool link_cong;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
98
99
  	u16 snt_unacked;
  	u16 snd_win;
60020e185   Jon Paul Maloy   tipc: propagate p...
100
  	u16 peer_caps;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
101
102
  	u16 rcv_unacked;
  	u16 rcv_win;
f2f8036e3   Erik Hugne   tipc: add support...
103
  	struct sockaddr_tipc remote;
07f6c4bc0   Ying Xue   tipc: convert tip...
104
105
  	struct rhash_head node;
  	struct rcu_head rcu;
301bae56f   Jon Paul Maloy   tipc: merge struc...
106
  };
b97bf3fd8   Per Liden   [TIPC] Initial merge
107

4f4482dcd   Jon Paul Maloy   tipc: compensate ...
108
  static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb);
676d23690   David S. Miller   net: Fix use afte...
109
  static void tipc_data_ready(struct sock *sk);
f288bef46   Ying Xue   tipc: fix race/in...
110
  static void tipc_write_space(struct sock *sk);
f4195d1ea   Ying Xue   tipc: avoid packe...
111
  static void tipc_sock_destruct(struct sock *sk);
247f0f3c3   Ying Xue   tipc: align tipc ...
112
113
  static int tipc_release(struct socket *sock);
  static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags);
0abd8ff21   Jon Paul Maloy   tipc: start using...
114
  static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p);
f2f2a96a2   Ying Xue   tipc: feed tipc s...
115
  static void tipc_sk_timeout(unsigned long data);
301bae56f   Jon Paul Maloy   tipc: merge struc...
116
  static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
117
  			   struct tipc_name_seq const *seq);
301bae56f   Jon Paul Maloy   tipc: merge struc...
118
  static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
119
  			    struct tipc_name_seq const *seq);
e05b31f4b   Ying Xue   tipc: make tipc s...
120
  static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid);
07f6c4bc0   Ying Xue   tipc: convert tip...
121
122
  static int tipc_sk_insert(struct tipc_sock *tsk);
  static void tipc_sk_remove(struct tipc_sock *tsk);
39a0295f9   Ying Xue   tipc: Don't use i...
123
124
125
  static int __tipc_send_stream(struct socket *sock, struct msghdr *m,
  			      size_t dsz);
  static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz);
b97bf3fd8   Per Liden   [TIPC] Initial merge
126

bca65eae3   Florian Westphal   [TIPC]: declare p...
127
128
129
  static const struct proto_ops packet_ops;
  static const struct proto_ops stream_ops;
  static const struct proto_ops msg_ops;
b97bf3fd8   Per Liden   [TIPC] Initial merge
130
  static struct proto tipc_proto;
6cca7289d   Herbert Xu   tipc: Use inlined...
131
  static const struct rhashtable_params tsk_rht_params;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
132
133
134
135
  static u32 tsk_own_node(struct tipc_sock *tsk)
  {
  	return msg_prevnode(&tsk->phdr);
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
136
  static u32 tsk_peer_node(struct tipc_sock *tsk)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
137
  {
301bae56f   Jon Paul Maloy   tipc: merge struc...
138
  	return msg_destnode(&tsk->phdr);
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
139
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
140
  static u32 tsk_peer_port(struct tipc_sock *tsk)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
141
  {
301bae56f   Jon Paul Maloy   tipc: merge struc...
142
  	return msg_destport(&tsk->phdr);
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
143
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
144
  static  bool tsk_unreliable(struct tipc_sock *tsk)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
145
  {
301bae56f   Jon Paul Maloy   tipc: merge struc...
146
  	return msg_src_droppable(&tsk->phdr) != 0;
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
147
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
148
  static void tsk_set_unreliable(struct tipc_sock *tsk, bool unreliable)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
149
  {
301bae56f   Jon Paul Maloy   tipc: merge struc...
150
  	msg_set_src_droppable(&tsk->phdr, unreliable ? 1 : 0);
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
151
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
152
  static bool tsk_unreturnable(struct tipc_sock *tsk)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
153
  {
301bae56f   Jon Paul Maloy   tipc: merge struc...
154
  	return msg_dest_droppable(&tsk->phdr) != 0;
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
155
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
156
  static void tsk_set_unreturnable(struct tipc_sock *tsk, bool unreturnable)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
157
  {
301bae56f   Jon Paul Maloy   tipc: merge struc...
158
  	msg_set_dest_droppable(&tsk->phdr, unreturnable ? 1 : 0);
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
159
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
160
  static int tsk_importance(struct tipc_sock *tsk)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
161
  {
301bae56f   Jon Paul Maloy   tipc: merge struc...
162
  	return msg_importance(&tsk->phdr);
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
163
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
164
  static int tsk_set_importance(struct tipc_sock *tsk, int imp)
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
165
166
167
  {
  	if (imp > TIPC_CRITICAL_IMPORTANCE)
  		return -EINVAL;
301bae56f   Jon Paul Maloy   tipc: merge struc...
168
  	msg_set_importance(&tsk->phdr, (u32)imp);
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
169
170
  	return 0;
  }
8826cde65   Jon Paul Maloy   tipc: aggregate p...
171

301bae56f   Jon Paul Maloy   tipc: merge struc...
172
173
174
175
  static struct tipc_sock *tipc_sk(const struct sock *sk)
  {
  	return container_of(sk, struct tipc_sock, sk);
  }
10724cc7b   Jon Paul Maloy   tipc: redesign co...
176
  static bool tsk_conn_cong(struct tipc_sock *tsk)
301bae56f   Jon Paul Maloy   tipc: merge struc...
177
  {
6998cc6ec   Jon Paul Maloy   tipc: resolve con...
178
  	return tsk->snt_unacked > tsk->snd_win;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  }
  
  /* tsk_blocks(): translate a buffer size in bytes to number of
   * advertisable blocks, taking into account the ratio truesize(len)/len
   * We can trust that this ratio is always < 4 for len >= FLOWCTL_BLK_SZ
   */
  static u16 tsk_adv_blocks(int len)
  {
  	return len / FLOWCTL_BLK_SZ / 4;
  }
  
  /* tsk_inc(): increment counter for sent or received data
   * - If block based flow control is not supported by peer we
   *   fall back to message based ditto, incrementing the counter
   */
  static u16 tsk_inc(struct tipc_sock *tsk, int msglen)
  {
  	if (likely(tsk->peer_caps & TIPC_BLOCK_FLOWCTL))
  		return ((msglen / FLOWCTL_BLK_SZ) + 1);
  	return 1;
301bae56f   Jon Paul Maloy   tipc: merge struc...
199
  }
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
200
  /**
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
201
   * tsk_advance_rx_queue - discard first buffer in socket receive queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
202
203
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
204
   */
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
205
  static void tsk_advance_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
206
  {
5f6d9123f   Allan Stephens   tipc: Eliminate t...
207
  	kfree_skb(__skb_dequeue(&sk->sk_receive_queue));
b97bf3fd8   Per Liden   [TIPC] Initial merge
208
  }
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  /* tipc_sk_respond() : send response message back to sender
   */
  static void tipc_sk_respond(struct sock *sk, struct sk_buff *skb, int err)
  {
  	u32 selector;
  	u32 dnode;
  	u32 onode = tipc_own_addr(sock_net(sk));
  
  	if (!tipc_msg_reverse(onode, &skb, err))
  		return;
  
  	dnode = msg_destnode(buf_msg(skb));
  	selector = msg_origport(buf_msg(skb));
  	tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector);
  }
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
224
  /**
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
225
   * tsk_rej_rx_queue - reject all buffers in socket receive queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
226
227
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
228
   */
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
229
  static void tsk_rej_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
230
  {
a6ca10944   Ying Xue   tipc: use generic...
231
  	struct sk_buff *skb;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
232

bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
233
234
  	while ((skb = __skb_dequeue(&sk->sk_receive_queue)))
  		tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
b97bf3fd8   Per Liden   [TIPC] Initial merge
235
  }
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
236
  /* tsk_peer_msg - verify if message was sent by connected port's peer
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
237
238
239
240
   *
   * Handles cases where the node's network address has changed from
   * the default of <0.0.0> to its configured setting.
   */
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
241
  static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg)
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
242
  {
347475395   Ying Xue   tipc: make tipc n...
243
  	struct tipc_net *tn = net_generic(sock_net(&tsk->sk), tipc_net_id);
301bae56f   Jon Paul Maloy   tipc: merge struc...
244
  	u32 peer_port = tsk_peer_port(tsk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
245
246
  	u32 orig_node;
  	u32 peer_node;
301bae56f   Jon Paul Maloy   tipc: merge struc...
247
  	if (unlikely(!tsk->connected))
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
248
249
250
251
252
253
  		return false;
  
  	if (unlikely(msg_origport(msg) != peer_port))
  		return false;
  
  	orig_node = msg_orignode(msg);
301bae56f   Jon Paul Maloy   tipc: merge struc...
254
  	peer_node = tsk_peer_node(tsk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
255
256
257
  
  	if (likely(orig_node == peer_node))
  		return true;
347475395   Ying Xue   tipc: make tipc n...
258
  	if (!orig_node && (peer_node == tn->own_addr))
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
259
  		return true;
347475395   Ying Xue   tipc: make tipc n...
260
  	if (!peer_node && (orig_node == tn->own_addr))
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
261
262
263
264
  		return true;
  
  	return false;
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
265
  /**
c5fa7b3cf   Ying Xue   tipc: introduce n...
266
   * tipc_sk_create - create a TIPC socket
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
267
   * @net: network namespace (must be default network)
b97bf3fd8   Per Liden   [TIPC] Initial merge
268
269
   * @sock: pre-allocated socket structure
   * @protocol: protocol indicator (must be 0)
3f378b684   Eric Paris   net: pass kern to...
270
   * @kern: caused by kernel or by userspace?
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
271
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
272
273
   * This routine creates additional data structures used by the TIPC socket,
   * initializes them, and links them together.
b97bf3fd8   Per Liden   [TIPC] Initial merge
274
275
276
   *
   * Returns 0 on success, errno otherwise
   */
58ed94424   Jon Paul Maloy   tipc: align usage...
277
278
  static int tipc_sk_create(struct net *net, struct socket *sock,
  			  int protocol, int kern)
b97bf3fd8   Per Liden   [TIPC] Initial merge
279
  {
c5898636c   Jon Paul Maloy   tipc: reduce usag...
280
  	struct tipc_net *tn;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
281
282
  	const struct proto_ops *ops;
  	socket_state state;
b97bf3fd8   Per Liden   [TIPC] Initial merge
283
  	struct sock *sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
284
  	struct tipc_sock *tsk;
5b8fa7ce8   Jon Paul Maloy   tipc: eliminate f...
285
  	struct tipc_msg *msg;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
286
287
  
  	/* Validate arguments */
b97bf3fd8   Per Liden   [TIPC] Initial merge
288
289
  	if (unlikely(protocol != 0))
  		return -EPROTONOSUPPORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
290
291
  	switch (sock->type) {
  	case SOCK_STREAM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
292
293
  		ops = &stream_ops;
  		state = SS_UNCONNECTED;
b97bf3fd8   Per Liden   [TIPC] Initial merge
294
295
  		break;
  	case SOCK_SEQPACKET:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
296
297
  		ops = &packet_ops;
  		state = SS_UNCONNECTED;
b97bf3fd8   Per Liden   [TIPC] Initial merge
298
299
  		break;
  	case SOCK_DGRAM:
b97bf3fd8   Per Liden   [TIPC] Initial merge
300
  	case SOCK_RDM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
301
302
  		ops = &msg_ops;
  		state = SS_READY;
b97bf3fd8   Per Liden   [TIPC] Initial merge
303
  		break;
499786516   Allan Stephens   [TIPC]: Improved ...
304
  	default:
499786516   Allan Stephens   [TIPC]: Improved ...
305
  		return -EPROTOTYPE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
306
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
307
  	/* Allocate socket's protocol area */
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
308
  	sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, kern);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
309
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
310
  		return -ENOMEM;
b97bf3fd8   Per Liden   [TIPC] Initial merge
311

58ed94424   Jon Paul Maloy   tipc: align usage...
312
  	tsk = tipc_sk(sk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
313
  	tsk->max_pkt = MAX_PKT_DEFAULT;
301bae56f   Jon Paul Maloy   tipc: merge struc...
314
315
  	INIT_LIST_HEAD(&tsk->publications);
  	msg = &tsk->phdr;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
316
317
  	tn = net_generic(sock_net(sk), tipc_net_id);
  	tipc_msg_init(tn->own_addr, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG,
5b8fa7ce8   Jon Paul Maloy   tipc: eliminate f...
318
  		      NAMED_H_SIZE, 0);
b97bf3fd8   Per Liden   [TIPC] Initial merge
319

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
320
  	/* Finish initializing socket data structures */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
321
322
  	sock->ops = ops;
  	sock->state = state;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
323
  	sock_init_data(sock, sk);
07f6c4bc0   Ying Xue   tipc: convert tip...
324
  	if (tipc_sk_insert(tsk)) {
c19ca6cb4   Masanari Iida   treewide: Fix typ...
325
326
  		pr_warn("Socket create failed; port number exhausted
  ");
07f6c4bc0   Ying Xue   tipc: convert tip...
327
328
329
  		return -EINVAL;
  	}
  	msg_set_origport(msg, tsk->portid);
3721e9c7c   Ying Xue   tipc: remove redu...
330
  	setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk);
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
331
  	sk->sk_backlog_rcv = tipc_backlog_rcv;
cc79dd1ba   Ying Xue   tipc: change sock...
332
  	sk->sk_rcvbuf = sysctl_tipc_rmem[1];
f288bef46   Ying Xue   tipc: fix race/in...
333
334
  	sk->sk_data_ready = tipc_data_ready;
  	sk->sk_write_space = tipc_write_space;
f4195d1ea   Ying Xue   tipc: avoid packe...
335
  	sk->sk_destruct = tipc_sock_destruct;
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
336
337
  	tsk->conn_timeout = CONN_TIMEOUT_DEFAULT;
  	atomic_set(&tsk->dupl_rcvcnt, 0);
7ef43ebaa   Allan Stephens   tipc: Fix race co...
338

10724cc7b   Jon Paul Maloy   tipc: redesign co...
339
340
341
  	/* Start out with safe limits until we receive an advertised window */
  	tsk->snd_win = tsk_adv_blocks(RCVBUF_MIN);
  	tsk->rcv_win = tsk->snd_win;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
342
  	if (sock->state == SS_READY) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
343
  		tsk_set_unreturnable(tsk, true);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
344
  		if (sock->type == SOCK_DGRAM)
301bae56f   Jon Paul Maloy   tipc: merge struc...
345
  			tsk_set_unreliable(tsk, true);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
346
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
347
348
  	return 0;
  }
07f6c4bc0   Ying Xue   tipc: convert tip...
349
350
351
352
353
354
  static void tipc_sk_callback(struct rcu_head *head)
  {
  	struct tipc_sock *tsk = container_of(head, struct tipc_sock, rcu);
  
  	sock_put(&tsk->sk);
  }
c5fa7b3cf   Ying Xue   tipc: introduce n...
355
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
356
   * tipc_release - destroy a TIPC socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
357
358
359
360
361
362
363
   * @sock: socket to destroy
   *
   * This routine cleans up any messages that are still queued on the socket.
   * For DGRAM and RDM socket types, all queued messages are rejected.
   * For SEQPACKET and STREAM socket types, the first message is rejected
   * and any others are discarded.  (If the first message on a STREAM socket
   * is partially-read, it is discarded and the next one is rejected instead.)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
364
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
365
366
367
368
369
370
   * NOTE: Rejected messages are not necessarily returned to the sender!  They
   * are returned or discarded according to the "destination droppable" setting
   * specified for the message by the sender.
   *
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
371
  static int tipc_release(struct socket *sock)
b97bf3fd8   Per Liden   [TIPC] Initial merge
372
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
373
  	struct sock *sk = sock->sk;
357c4774b   Sasha Levin   tipc: correctly h...
374
  	struct net *net;
58ed94424   Jon Paul Maloy   tipc: align usage...
375
  	struct tipc_sock *tsk;
a6ca10944   Ying Xue   tipc: use generic...
376
  	struct sk_buff *skb;
1ea23a211   Ying Xue   tipc: uncondition...
377
  	u32 dnode;
b97bf3fd8   Per Liden   [TIPC] Initial merge
378

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
379
380
381
382
  	/*
  	 * Exit if socket isn't fully initialized (occurs when a failed accept()
  	 * releases a pre-allocated child socket that was never used)
  	 */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
383
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
384
  		return 0;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
385

357c4774b   Sasha Levin   tipc: correctly h...
386
  	net = sock_net(sk);
58ed94424   Jon Paul Maloy   tipc: align usage...
387
  	tsk = tipc_sk(sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
388
389
390
391
392
393
  	lock_sock(sk);
  
  	/*
  	 * Reject all unreceived messages, except on an active connection
  	 * (which disconnects locally & sends a 'FIN+' to peer)
  	 */
301bae56f   Jon Paul Maloy   tipc: merge struc...
394
  	dnode = tsk_peer_node(tsk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
395
  	while (sock->state != SS_DISCONNECTING) {
a6ca10944   Ying Xue   tipc: use generic...
396
397
  		skb = __skb_dequeue(&sk->sk_receive_queue);
  		if (skb == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
398
  			break;
a6ca10944   Ying Xue   tipc: use generic...
399
400
  		if (TIPC_SKB_CB(skb)->handle != NULL)
  			kfree_skb(skb);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
401
402
403
404
  		else {
  			if ((sock->state == SS_CONNECTING) ||
  			    (sock->state == SS_CONNECTED)) {
  				sock->state = SS_DISCONNECTING;
301bae56f   Jon Paul Maloy   tipc: merge struc...
405
  				tsk->connected = 0;
f2f9800d4   Ying Xue   tipc: make tipc n...
406
  				tipc_node_remove_conn(net, dnode, tsk->portid);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
407
  			}
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
408
  			tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
409
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
410
  	}
301bae56f   Jon Paul Maloy   tipc: merge struc...
411
  	tipc_sk_withdraw(tsk, 0, NULL);
1ea23a211   Ying Xue   tipc: uncondition...
412
  	sk_stop_timer(sk, &sk->sk_timer);
07f6c4bc0   Ying Xue   tipc: convert tip...
413
  	tipc_sk_remove(tsk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
414
  	if (tsk->connected) {
c5898636c   Jon Paul Maloy   tipc: reduce usag...
415
  		skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
347475395   Ying Xue   tipc: make tipc n...
416
  				      TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
c5898636c   Jon Paul Maloy   tipc: reduce usag...
417
  				      tsk_own_node(tsk), tsk_peer_port(tsk),
07f6c4bc0   Ying Xue   tipc: convert tip...
418
  				      tsk->portid, TIPC_ERR_NO_PORT);
a6ca10944   Ying Xue   tipc: use generic...
419
  		if (skb)
af9b028e2   Jon Paul Maloy   tipc: make media ...
420
  			tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
f2f9800d4   Ying Xue   tipc: make tipc n...
421
  		tipc_node_remove_conn(net, dnode, tsk->portid);
5b8fa7ce8   Jon Paul Maloy   tipc: eliminate f...
422
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
423

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
424
  	/* Reject any messages that accumulated in backlog queue */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
425
426
  	sock->state = SS_DISCONNECTING;
  	release_sock(sk);
07f6c4bc0   Ying Xue   tipc: convert tip...
427
428
  
  	call_rcu(&tsk->rcu, tipc_sk_callback);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
429
  	sock->sk = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
430

065d7e395   Geert Uytterhoeven   tipc: Let tipc_re...
431
  	return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
432
433
434
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
435
   * tipc_bind - associate or disassocate TIPC name(s) with a socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
436
437
438
   * @sock: socket structure
   * @uaddr: socket address describing name(s) and desired operation
   * @uaddr_len: size of socket address data structure
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
439
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
440
441
442
   * Name and name sequence binding is indicated using a positive scope value;
   * a negative scope value unbinds the specified name.  Specifying no name
   * (i.e. a socket address length of 0) unbinds all names from the socket.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
443
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
444
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
445
446
447
   *
   * NOTE: This routine doesn't need to take the socket lock since it doesn't
   *       access any non-constant socket information.
b97bf3fd8   Per Liden   [TIPC] Initial merge
448
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
449
450
  static int tipc_bind(struct socket *sock, struct sockaddr *uaddr,
  		     int uaddr_len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
451
  {
84602761c   Ying Xue   tipc: fix deadloc...
452
  	struct sock *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
453
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
58ed94424   Jon Paul Maloy   tipc: align usage...
454
  	struct tipc_sock *tsk = tipc_sk(sk);
84602761c   Ying Xue   tipc: fix deadloc...
455
  	int res = -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
456

84602761c   Ying Xue   tipc: fix deadloc...
457
458
  	lock_sock(sk);
  	if (unlikely(!uaddr_len)) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
459
  		res = tipc_sk_withdraw(tsk, 0, NULL);
84602761c   Ying Xue   tipc: fix deadloc...
460
461
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
462

84602761c   Ying Xue   tipc: fix deadloc...
463
464
465
466
467
468
469
470
  	if (uaddr_len < sizeof(struct sockaddr_tipc)) {
  		res = -EINVAL;
  		goto exit;
  	}
  	if (addr->family != AF_TIPC) {
  		res = -EAFNOSUPPORT;
  		goto exit;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
471

b97bf3fd8   Per Liden   [TIPC] Initial merge
472
473
  	if (addr->addrtype == TIPC_ADDR_NAME)
  		addr->addr.nameseq.upper = addr->addr.nameseq.lower;
84602761c   Ying Xue   tipc: fix deadloc...
474
475
476
477
  	else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
  		res = -EAFNOSUPPORT;
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
478

13a2e8987   Ying Xue   tipc: convert top...
479
  	if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
7d0ab17b7   Ying Xue   tipc: convert con...
480
  	    (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
84602761c   Ying Xue   tipc: fix deadloc...
481
482
483
484
  	    (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
  		res = -EACCES;
  		goto exit;
  	}
c422f1bdc   Allan Stephens   tipc: Simplify en...
485

84602761c   Ying Xue   tipc: fix deadloc...
486
  	res = (addr->scope > 0) ?
301bae56f   Jon Paul Maloy   tipc: merge struc...
487
488
  		tipc_sk_publish(tsk, addr->scope, &addr->addr.nameseq) :
  		tipc_sk_withdraw(tsk, -addr->scope, &addr->addr.nameseq);
84602761c   Ying Xue   tipc: fix deadloc...
489
490
491
  exit:
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
492
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
493
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
494
   * tipc_getname - get port ID of socket or peer socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
495
496
497
   * @sock: socket structure
   * @uaddr: area for returned socket address
   * @uaddr_len: area for returned length of socket address
2da59918e   Allan Stephens   tipc: Fix race co...
498
   * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
499
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
500
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
501
   *
2da59918e   Allan Stephens   tipc: Fix race co...
502
503
   * NOTE: This routine doesn't need to take the socket lock since it only
   *       accesses socket information that is unchanging (or which changes in
0e65967e3   Allan Stephens   tipc: cleanup var...
504
   *       a completely predictable manner).
b97bf3fd8   Per Liden   [TIPC] Initial merge
505
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
506
507
  static int tipc_getname(struct socket *sock, struct sockaddr *uaddr,
  			int *uaddr_len, int peer)
b97bf3fd8   Per Liden   [TIPC] Initial merge
508
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
509
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
58ed94424   Jon Paul Maloy   tipc: align usage...
510
  	struct tipc_sock *tsk = tipc_sk(sock->sk);
347475395   Ying Xue   tipc: make tipc n...
511
  	struct tipc_net *tn = net_generic(sock_net(sock->sk), tipc_net_id);
b97bf3fd8   Per Liden   [TIPC] Initial merge
512

88f8a5e3e   Kulikov Vasiliy   net: tipc: fix in...
513
  	memset(addr, 0, sizeof(*addr));
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
514
  	if (peer) {
2da59918e   Allan Stephens   tipc: Fix race co...
515
516
517
  		if ((sock->state != SS_CONNECTED) &&
  			((peer != 2) || (sock->state != SS_DISCONNECTING)))
  			return -ENOTCONN;
301bae56f   Jon Paul Maloy   tipc: merge struc...
518
519
  		addr->addr.id.ref = tsk_peer_port(tsk);
  		addr->addr.id.node = tsk_peer_node(tsk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
520
  	} else {
07f6c4bc0   Ying Xue   tipc: convert tip...
521
  		addr->addr.id.ref = tsk->portid;
347475395   Ying Xue   tipc: make tipc n...
522
  		addr->addr.id.node = tn->own_addr;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
523
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
524
525
526
527
528
  
  	*uaddr_len = sizeof(*addr);
  	addr->addrtype = TIPC_ADDR_ID;
  	addr->family = AF_TIPC;
  	addr->scope = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
529
  	addr->addr.name.domain = 0;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
530
  	return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
531
532
533
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
534
   * tipc_poll - read and possibly block on pollmask
b97bf3fd8   Per Liden   [TIPC] Initial merge
535
536
537
538
   * @file: file structure associated with the socket
   * @sock: socket for which to calculate the poll bits
   * @wait: ???
   *
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
539
540
541
542
543
544
545
546
547
   * Returns pollmask value
   *
   * COMMENTARY:
   * It appears that the usual socket locking mechanisms are not useful here
   * since the pollmask info is potentially out-of-date the moment this routine
   * exits.  TCP and other protocols seem to rely on higher level poll routines
   * to handle any preventable race conditions, so TIPC will do the same ...
   *
   * TIPC sets the returned events as follows:
f662c0705   Allan Stephens   tipc: correct pro...
548
549
550
551
   *
   * socket state		flags set
   * ------------		---------
   * unconnected		no read flags
c4fc298ab   Erik Hugne   tipc: return POLL...
552
   *			POLLOUT if port is not congested
f662c0705   Allan Stephens   tipc: correct pro...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
   *
   * 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.
b97bf3fd8   Per Liden   [TIPC] Initial merge
572
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
573
574
  static unsigned int tipc_poll(struct file *file, struct socket *sock,
  			      poll_table *wait)
b97bf3fd8   Per Liden   [TIPC] Initial merge
575
  {
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
576
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
577
  	struct tipc_sock *tsk = tipc_sk(sk);
f662c0705   Allan Stephens   tipc: correct pro...
578
  	u32 mask = 0;
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
579

f288bef46   Ying Xue   tipc: fix race/in...
580
  	sock_poll_wait(file, sk_sleep(sk), wait);
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
581

f662c0705   Allan Stephens   tipc: correct pro...
582
  	switch ((int)sock->state) {
c4fc298ab   Erik Hugne   tipc: return POLL...
583
  	case SS_UNCONNECTED:
60120526c   Jon Paul Maloy   tipc: simplify co...
584
  		if (!tsk->link_cong)
c4fc298ab   Erik Hugne   tipc: return POLL...
585
586
  			mask |= POLLOUT;
  		break;
f662c0705   Allan Stephens   tipc: correct pro...
587
588
  	case SS_READY:
  	case SS_CONNECTED:
301bae56f   Jon Paul Maloy   tipc: merge struc...
589
  		if (!tsk->link_cong && !tsk_conn_cong(tsk))
f662c0705   Allan Stephens   tipc: correct pro...
590
591
592
593
594
595
596
597
598
599
600
  			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;
  	}
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
601
602
  
  	return mask;
b97bf3fd8   Per Liden   [TIPC] Initial merge
603
  }
0abd8ff21   Jon Paul Maloy   tipc: start using...
604
605
606
607
  /**
   * tipc_sendmcast - send multicast message
   * @sock: socket structure
   * @seq: destination address
562640f3c   Al Viro   tipc_sendmsg(): p...
608
   * @msg: message to send
0abd8ff21   Jon Paul Maloy   tipc: start using...
609
610
611
612
613
614
615
   * @dsz: total length of message data
   * @timeo: timeout to wait for wakeup
   *
   * Called from function tipc_sendmsg(), which has done all sanity checks
   * Returns the number of bytes sent on success, or errno
   */
  static int tipc_sendmcast(struct  socket *sock, struct tipc_name_seq *seq,
562640f3c   Al Viro   tipc_sendmsg(): p...
616
  			  struct msghdr *msg, size_t dsz, long timeo)
0abd8ff21   Jon Paul Maloy   tipc: start using...
617
618
  {
  	struct sock *sk = sock->sk;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
619
  	struct tipc_sock *tsk = tipc_sk(sk);
f2f9800d4   Ying Xue   tipc: make tipc n...
620
  	struct net *net = sock_net(sk);
c5898636c   Jon Paul Maloy   tipc: reduce usag...
621
  	struct tipc_msg *mhdr = &tsk->phdr;
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
622
  	struct sk_buff_head pktchain;
f25dcc768   Al Viro   tipc: tipc ->send...
623
  	struct iov_iter save = msg->msg_iter;
0abd8ff21   Jon Paul Maloy   tipc: start using...
624
625
626
627
628
629
630
631
632
633
634
  	uint mtu;
  	int rc;
  
  	msg_set_type(mhdr, TIPC_MCAST_MSG);
  	msg_set_lookup_scope(mhdr, TIPC_CLUSTER_SCOPE);
  	msg_set_destport(mhdr, 0);
  	msg_set_destnode(mhdr, 0);
  	msg_set_nametype(mhdr, seq->type);
  	msg_set_namelower(mhdr, seq->lower);
  	msg_set_nameupper(mhdr, seq->upper);
  	msg_set_hdr_sz(mhdr, MCAST_H_SIZE);
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
635
  	skb_queue_head_init(&pktchain);
0abd8ff21   Jon Paul Maloy   tipc: start using...
636
  new_mtu:
959e1781a   Jon Paul Maloy   tipc: introduce j...
637
  	mtu = tipc_bcast_get_mtu(net);
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
638
  	rc = tipc_msg_build(mhdr, msg, 0, dsz, mtu, &pktchain);
0abd8ff21   Jon Paul Maloy   tipc: start using...
639
640
641
642
  	if (unlikely(rc < 0))
  		return rc;
  
  	do {
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
643
  		rc = tipc_bcast_xmit(net, &pktchain);
22d85c794   Jon Paul Maloy   tipc: change sk_b...
644
645
646
647
648
649
650
651
  		if (likely(!rc))
  			return dsz;
  
  		if (rc == -ELINKCONG) {
  			tsk->link_cong = 1;
  			rc = tipc_wait_for_sndmsg(sock, &timeo);
  			if (!rc)
  				continue;
0abd8ff21   Jon Paul Maloy   tipc: start using...
652
  		}
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
653
  		__skb_queue_purge(&pktchain);
f25dcc768   Al Viro   tipc: tipc ->send...
654
655
  		if (rc == -EMSGSIZE) {
  			msg->msg_iter = save;
0abd8ff21   Jon Paul Maloy   tipc: start using...
656
  			goto new_mtu;
f25dcc768   Al Viro   tipc: tipc ->send...
657
  		}
22d85c794   Jon Paul Maloy   tipc: change sk_b...
658
659
  		break;
  	} while (1);
0abd8ff21   Jon Paul Maloy   tipc: start using...
660
661
  	return rc;
  }
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
662
663
664
665
666
667
  /**
   * tipc_sk_mcast_rcv - Deliver multicast messages to all destination sockets
   * @arrvq: queue with arriving messages, to be cloned after destination lookup
   * @inputq: queue with cloned messages, delivered to socket after dest lookup
   *
   * Multi-threaded: parallel calls with reference to same queues may occur
078bec826   Jon Paul Maloy   tipc: add new fun...
668
   */
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
669
670
  void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
  		       struct sk_buff_head *inputq)
078bec826   Jon Paul Maloy   tipc: add new fun...
671
  {
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
672
  	struct tipc_msg *msg;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
673
  	struct tipc_plist dports;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
674
  	u32 portid;
078bec826   Jon Paul Maloy   tipc: add new fun...
675
  	u32 scope = TIPC_CLUSTER_SCOPE;
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
676
677
678
  	struct sk_buff_head tmpq;
  	uint hsz;
  	struct sk_buff *skb, *_skb;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
679

cb1b72809   Jon Paul Maloy   tipc: eliminate r...
680
  	__skb_queue_head_init(&tmpq);
3c724acdd   Jon Paul Maloy   tipc: simplify so...
681
  	tipc_plist_init(&dports);
078bec826   Jon Paul Maloy   tipc: add new fun...
682

cb1b72809   Jon Paul Maloy   tipc: eliminate r...
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
  	skb = tipc_skb_peek(arrvq, &inputq->lock);
  	for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) {
  		msg = buf_msg(skb);
  		hsz = skb_headroom(skb) + msg_hdr_sz(msg);
  
  		if (in_own_node(net, msg_orignode(msg)))
  			scope = TIPC_NODE_SCOPE;
  
  		/* Create destination port list and message clones: */
  		tipc_nametbl_mc_translate(net,
  					  msg_nametype(msg), msg_namelower(msg),
  					  msg_nameupper(msg), scope, &dports);
  		portid = tipc_plist_pop(&dports);
  		for (; portid; portid = tipc_plist_pop(&dports)) {
  			_skb = __pskb_copy(skb, hsz, GFP_ATOMIC);
  			if (_skb) {
  				msg_set_destport(buf_msg(_skb), portid);
  				__skb_queue_tail(&tmpq, _skb);
  				continue;
  			}
  			pr_warn("Failed to clone mcast rcv buffer
  ");
078bec826   Jon Paul Maloy   tipc: add new fun...
705
  		}
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
706
707
708
709
710
711
712
713
714
  		/* Append to inputq if not already done by other thread */
  		spin_lock_bh(&inputq->lock);
  		if (skb_peek(arrvq) == skb) {
  			skb_queue_splice_tail_init(&tmpq, inputq);
  			kfree_skb(__skb_dequeue(arrvq));
  		}
  		spin_unlock_bh(&inputq->lock);
  		__skb_queue_purge(&tmpq);
  		kfree_skb(skb);
078bec826   Jon Paul Maloy   tipc: add new fun...
715
  	}
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
716
  	tipc_sk_rcv(net, inputq);
078bec826   Jon Paul Maloy   tipc: add new fun...
717
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
718
  /**
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
719
720
   * tipc_sk_proto_rcv - receive a connection mng protocol message
   * @tsk: receiving socket
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
721
   * @skb: pointer to message buffer.
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
722
   */
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
723
724
  static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,
  			      struct sk_buff_head *xmitq)
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
725
  {
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
726
  	struct sock *sk = &tsk->sk;
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
727
  	u32 onode = tsk_own_node(tsk);
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
728
729
  	struct tipc_msg *hdr = buf_msg(skb);
  	int mtyp = msg_type(hdr);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
730
  	bool conn_cong;
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
731

ac0074ee7   Jon Paul Maloy   tipc: clean up co...
732
  	/* Ignore if connection cannot be validated: */
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
733
  	if (!tsk_peer_msg(tsk, hdr))
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
734
  		goto exit;
301bae56f   Jon Paul Maloy   tipc: merge struc...
735
  	tsk->probing_state = TIPC_CONN_OK;
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
736

bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
737
738
  	if (mtyp == CONN_PROBE) {
  		msg_set_type(hdr, CONN_PROBE_REPLY);
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
739
740
  		if (tipc_msg_reverse(onode, &skb, TIPC_OK))
  			__skb_queue_tail(xmitq, skb);
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
741
742
  		return;
  	} else if (mtyp == CONN_ACK) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
743
  		conn_cong = tsk_conn_cong(tsk);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
744
745
746
  		tsk->snt_unacked -= msg_conn_ack(hdr);
  		if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL)
  			tsk->snd_win = msg_adv_win(hdr);
60120526c   Jon Paul Maloy   tipc: simplify co...
747
  		if (conn_cong)
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
748
749
750
751
  			sk->sk_write_space(sk);
  	} else if (mtyp != CONN_PROBE_REPLY) {
  		pr_warn("Received unknown CONN_PROTO msg
  ");
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
752
  	}
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
753
  exit:
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
754
  	kfree_skb(skb);
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
755
  }
3f40504f7   Ying Xue   tipc: standardize...
756
757
758
  static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
  {
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
759
  	struct tipc_sock *tsk = tipc_sk(sk);
3f40504f7   Ying Xue   tipc: standardize...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
  	DEFINE_WAIT(wait);
  	int done;
  
  	do {
  		int err = sock_error(sk);
  		if (err)
  			return err;
  		if (sock->state == SS_DISCONNECTING)
  			return -EPIPE;
  		if (!*timeo_p)
  			return -EAGAIN;
  		if (signal_pending(current))
  			return sock_intr_errno(*timeo_p);
  
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
60120526c   Jon Paul Maloy   tipc: simplify co...
775
  		done = sk_wait_event(sk, timeo_p, !tsk->link_cong);
3f40504f7   Ying Xue   tipc: standardize...
776
777
778
779
  		finish_wait(sk_sleep(sk), &wait);
  	} while (!done);
  	return 0;
  }
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
780
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
781
   * tipc_sendmsg - send message in connectionless manner
b97bf3fd8   Per Liden   [TIPC] Initial merge
782
783
   * @sock: socket structure
   * @m: message to send
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
784
   * @dsz: amount of user data to be sent
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
785
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
786
   * Message must have an destination specified explicitly.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
787
   * Used for SOCK_RDM and SOCK_DGRAM messages,
b97bf3fd8   Per Liden   [TIPC] Initial merge
788
789
   * and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections.
   * (Note: 'SYN+' is prohibited on SOCK_STREAM.)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
790
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
791
792
   * Returns the number of bytes sent on success, or errno otherwise
   */
1b7841404   Ying Xue   net: Remove iocb ...
793
  static int tipc_sendmsg(struct socket *sock,
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
794
  			struct msghdr *m, size_t dsz)
b97bf3fd8   Per Liden   [TIPC] Initial merge
795
  {
39a0295f9   Ying Xue   tipc: Don't use i...
796
797
798
799
800
801
802
803
804
805
806
807
  	struct sock *sk = sock->sk;
  	int ret;
  
  	lock_sock(sk);
  	ret = __tipc_sendmsg(sock, m, dsz);
  	release_sock(sk);
  
  	return ret;
  }
  
  static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
  {
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
808
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
809
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
810
  	struct tipc_sock *tsk = tipc_sk(sk);
f2f9800d4   Ying Xue   tipc: make tipc n...
811
  	struct net *net = sock_net(sk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
812
  	struct tipc_msg *mhdr = &tsk->phdr;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
813
  	u32 dnode, dport;
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
814
  	struct sk_buff_head pktchain;
a6ca10944   Ying Xue   tipc: use generic...
815
  	struct sk_buff *skb;
f2f8036e3   Erik Hugne   tipc: add support...
816
  	struct tipc_name_seq *seq;
f25dcc768   Al Viro   tipc: tipc ->send...
817
  	struct iov_iter save;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
818
  	u32 mtu;
3f40504f7   Ying Xue   tipc: standardize...
819
  	long timeo;
88b17b6a2   Erik Hugne   tipc: drop tx sid...
820
  	int rc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
821

e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
822
  	if (dsz > TIPC_MAX_USER_MSG_SIZE)
c29c3f70c   Allan Stephens   tipc: Abort exces...
823
  		return -EMSGSIZE;
f2f8036e3   Erik Hugne   tipc: add support...
824
825
826
827
828
829
830
831
832
  	if (unlikely(!dest)) {
  		if (tsk->connected && sock->state == SS_READY)
  			dest = &tsk->remote;
  		else
  			return -EDESTADDRREQ;
  	} else if (unlikely(m->msg_namelen < sizeof(*dest)) ||
  		   dest->family != AF_TIPC) {
  		return -EINVAL;
  	}
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
833
  	if (unlikely(sock->state != SS_READY)) {
39a0295f9   Ying Xue   tipc: Don't use i...
834
835
836
837
838
839
  		if (sock->state == SS_LISTENING)
  			return -EPIPE;
  		if (sock->state != SS_UNCONNECTED)
  			return -EISCONN;
  		if (tsk->published)
  			return -EOPNOTSUPP;
3388007bc   Allan Stephens   [TIPC]: Implied c...
840
  		if (dest->addrtype == TIPC_ADDR_NAME) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
841
842
  			tsk->conn_type = dest->addr.name.name.type;
  			tsk->conn_instance = dest->addr.name.name.instance;
3388007bc   Allan Stephens   [TIPC]: Implied c...
843
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
844
  	}
f2f8036e3   Erik Hugne   tipc: add support...
845
  	seq = &dest->addr.nameseq;
3f40504f7   Ying Xue   tipc: standardize...
846
  	timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
847
848
  
  	if (dest->addrtype == TIPC_ADDR_MCAST) {
39a0295f9   Ying Xue   tipc: Don't use i...
849
  		return tipc_sendmcast(sock, seq, m, dsz, timeo);
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
850
851
852
853
854
855
856
857
858
859
860
  	} else if (dest->addrtype == TIPC_ADDR_NAME) {
  		u32 type = dest->addr.name.name.type;
  		u32 inst = dest->addr.name.name.instance;
  		u32 domain = dest->addr.name.domain;
  
  		dnode = domain;
  		msg_set_type(mhdr, TIPC_NAMED_MSG);
  		msg_set_hdr_sz(mhdr, NAMED_H_SIZE);
  		msg_set_nametype(mhdr, type);
  		msg_set_nameinst(mhdr, inst);
  		msg_set_lookup_scope(mhdr, tipc_addr_scope(domain));
4ac1c8d0e   Ying Xue   tipc: name tipc n...
861
  		dport = tipc_nametbl_translate(net, type, inst, &dnode);
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
862
863
  		msg_set_destnode(mhdr, dnode);
  		msg_set_destport(mhdr, dport);
39a0295f9   Ying Xue   tipc: Don't use i...
864
865
  		if (unlikely(!dport && !dnode))
  			return -EHOSTUNREACH;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
866
867
868
869
870
871
872
873
  	} else if (dest->addrtype == TIPC_ADDR_ID) {
  		dnode = dest->addr.id.node;
  		msg_set_type(mhdr, TIPC_DIRECT_MSG);
  		msg_set_lookup_scope(mhdr, 0);
  		msg_set_destnode(mhdr, dnode);
  		msg_set_destport(mhdr, dest->addr.id.ref);
  		msg_set_hdr_sz(mhdr, BASIC_H_SIZE);
  	}
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
874
  	skb_queue_head_init(&pktchain);
f25dcc768   Al Viro   tipc: tipc ->send...
875
  	save = m->msg_iter;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
876
  new_mtu:
f2f9800d4   Ying Xue   tipc: make tipc n...
877
  	mtu = tipc_node_get_mtu(net, dnode, tsk->portid);
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
878
  	rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, &pktchain);
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
879
  	if (rc < 0)
39a0295f9   Ying Xue   tipc: Don't use i...
880
  		return rc;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
881
882
  
  	do {
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
883
  		skb = skb_peek(&pktchain);
a6ca10944   Ying Xue   tipc: use generic...
884
  		TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
885
  		rc = tipc_node_xmit(net, &pktchain, dnode, tsk->portid);
22d85c794   Jon Paul Maloy   tipc: change sk_b...
886
  		if (likely(!rc)) {
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
887
  			if (sock->state != SS_READY)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
888
  				sock->state = SS_CONNECTING;
22d85c794   Jon Paul Maloy   tipc: change sk_b...
889
  			return dsz;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
890
  		}
22d85c794   Jon Paul Maloy   tipc: change sk_b...
891
892
893
894
895
896
  		if (rc == -ELINKCONG) {
  			tsk->link_cong = 1;
  			rc = tipc_wait_for_sndmsg(sock, &timeo);
  			if (!rc)
  				continue;
  		}
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
897
  		__skb_queue_purge(&pktchain);
f25dcc768   Al Viro   tipc: tipc ->send...
898
899
  		if (rc == -EMSGSIZE) {
  			m->msg_iter = save;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
900
  			goto new_mtu;
f25dcc768   Al Viro   tipc: tipc ->send...
901
  		}
22d85c794   Jon Paul Maloy   tipc: change sk_b...
902
903
  		break;
  	} while (1);
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
904
905
  
  	return rc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
906
  }
391a6dd1d   Ying Xue   tipc: standardize...
907
908
909
  static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
  {
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
910
  	struct tipc_sock *tsk = tipc_sk(sk);
391a6dd1d   Ying Xue   tipc: standardize...
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
  	DEFINE_WAIT(wait);
  	int done;
  
  	do {
  		int err = sock_error(sk);
  		if (err)
  			return err;
  		if (sock->state == SS_DISCONNECTING)
  			return -EPIPE;
  		else if (sock->state != SS_CONNECTED)
  			return -ENOTCONN;
  		if (!*timeo_p)
  			return -EAGAIN;
  		if (signal_pending(current))
  			return sock_intr_errno(*timeo_p);
  
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  		done = sk_wait_event(sk, timeo_p,
60120526c   Jon Paul Maloy   tipc: simplify co...
929
  				     (!tsk->link_cong &&
301bae56f   Jon Paul Maloy   tipc: merge struc...
930
931
  				      !tsk_conn_cong(tsk)) ||
  				     !tsk->connected);
391a6dd1d   Ying Xue   tipc: standardize...
932
933
934
935
  		finish_wait(sk_sleep(sk), &wait);
  	} while (!done);
  	return 0;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
936
  /**
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
937
   * tipc_send_stream - send stream-oriented data
b97bf3fd8   Per Liden   [TIPC] Initial merge
938
   * @sock: socket structure
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
939
940
   * @m: data to send
   * @dsz: total length of data to be transmitted
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
941
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
942
   * Used for SOCK_STREAM data.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
943
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
944
945
   * Returns the number of bytes sent on success (or partial success),
   * or errno if no data sent
b97bf3fd8   Per Liden   [TIPC] Initial merge
946
   */
1b7841404   Ying Xue   net: Remove iocb ...
947
  static int tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
b97bf3fd8   Per Liden   [TIPC] Initial merge
948
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
949
  	struct sock *sk = sock->sk;
39a0295f9   Ying Xue   tipc: Don't use i...
950
951
952
953
954
955
956
957
958
959
960
961
  	int ret;
  
  	lock_sock(sk);
  	ret = __tipc_send_stream(sock, m, dsz);
  	release_sock(sk);
  
  	return ret;
  }
  
  static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
  {
  	struct sock *sk = sock->sk;
f2f9800d4   Ying Xue   tipc: make tipc n...
962
  	struct net *net = sock_net(sk);
58ed94424   Jon Paul Maloy   tipc: align usage...
963
  	struct tipc_sock *tsk = tipc_sk(sk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
964
  	struct tipc_msg *mhdr = &tsk->phdr;
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
965
  	struct sk_buff_head pktchain;
342dfc306   Steffen Hurrle   net: add build-ti...
966
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
07f6c4bc0   Ying Xue   tipc: convert tip...
967
  	u32 portid = tsk->portid;
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
968
  	int rc = -EINVAL;
391a6dd1d   Ying Xue   tipc: standardize...
969
  	long timeo;
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
970
971
  	u32 dnode;
  	uint mtu, send, sent = 0;
f25dcc768   Al Viro   tipc: tipc ->send...
972
  	struct iov_iter save;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
973
  	int hlen = MIN_H_SIZE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
974
975
  
  	/* Handle implied connection establishment */
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
976
  	if (unlikely(dest)) {
39a0295f9   Ying Xue   tipc: Don't use i...
977
  		rc = __tipc_sendmsg(sock, m, dsz);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
978
  		hlen = msg_hdr_sz(mhdr);
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
979
  		if (dsz && (dsz == rc))
10724cc7b   Jon Paul Maloy   tipc: redesign co...
980
  			tsk->snt_unacked = tsk_inc(tsk, dsz + hlen);
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
981
982
983
  		return rc;
  	}
  	if (dsz > (uint)INT_MAX)
c29c3f70c   Allan Stephens   tipc: Abort exces...
984
  		return -EMSGSIZE;
391a6dd1d   Ying Xue   tipc: standardize...
985
986
  	if (unlikely(sock->state != SS_CONNECTED)) {
  		if (sock->state == SS_DISCONNECTING)
39a0295f9   Ying Xue   tipc: Don't use i...
987
  			return -EPIPE;
391a6dd1d   Ying Xue   tipc: standardize...
988
  		else
39a0295f9   Ying Xue   tipc: Don't use i...
989
  			return -ENOTCONN;
391a6dd1d   Ying Xue   tipc: standardize...
990
  	}
1d835874a   Ying Xue   tipc: Add support...
991

391a6dd1d   Ying Xue   tipc: standardize...
992
  	timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
301bae56f   Jon Paul Maloy   tipc: merge struc...
993
  	dnode = tsk_peer_node(tsk);
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
994
  	skb_queue_head_init(&pktchain);
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
995
996
  
  next:
f25dcc768   Al Viro   tipc: tipc ->send...
997
  	save = m->msg_iter;
301bae56f   Jon Paul Maloy   tipc: merge struc...
998
  	mtu = tsk->max_pkt;
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
999
  	send = min_t(uint, dsz - sent, TIPC_MAX_USER_MSG_SIZE);
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
1000
  	rc = tipc_msg_build(mhdr, m, sent, send, mtu, &pktchain);
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1001
  	if (unlikely(rc < 0))
39a0295f9   Ying Xue   tipc: Don't use i...
1002
  		return rc;
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
1003

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1004
  	do {
301bae56f   Jon Paul Maloy   tipc: merge struc...
1005
  		if (likely(!tsk_conn_cong(tsk))) {
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
1006
  			rc = tipc_node_xmit(net, &pktchain, dnode, portid);
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1007
  			if (likely(!rc)) {
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1008
  				tsk->snt_unacked += tsk_inc(tsk, send + hlen);
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1009
1010
  				sent += send;
  				if (sent == dsz)
22d85c794   Jon Paul Maloy   tipc: change sk_b...
1011
  					return dsz;
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1012
1013
1014
  				goto next;
  			}
  			if (rc == -EMSGSIZE) {
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
1015
  				__skb_queue_purge(&pktchain);
f2f9800d4   Ying Xue   tipc: make tipc n...
1016
1017
  				tsk->max_pkt = tipc_node_get_mtu(net, dnode,
  								 portid);
f25dcc768   Al Viro   tipc: tipc ->send...
1018
  				m->msg_iter = save;
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1019
1020
1021
1022
  				goto next;
  			}
  			if (rc != -ELINKCONG)
  				break;
22d85c794   Jon Paul Maloy   tipc: change sk_b...
1023

50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
1024
  			tsk->link_cong = 1;
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1025
1026
1027
  		}
  		rc = tipc_wait_for_sndpkt(sock, &timeo);
  	} while (!rc);
39a0295f9   Ying Xue   tipc: Don't use i...
1028

f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
1029
  	__skb_queue_purge(&pktchain);
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1030
  	return sent ? sent : rc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1031
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1032
  /**
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1033
   * tipc_send_packet - send a connection-oriented message
b97bf3fd8   Per Liden   [TIPC] Initial merge
1034
   * @sock: socket structure
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1035
1036
   * @m: message to send
   * @dsz: length of data to be transmitted
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1037
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1038
   * Used for SOCK_SEQPACKET messages.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1039
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1040
   * Returns the number of bytes sent on success, or errno otherwise
b97bf3fd8   Per Liden   [TIPC] Initial merge
1041
   */
1b7841404   Ying Xue   net: Remove iocb ...
1042
  static int tipc_send_packet(struct socket *sock, struct msghdr *m, size_t dsz)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1043
  {
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1044
1045
  	if (dsz > TIPC_MAX_USER_MSG_SIZE)
  		return -EMSGSIZE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1046

1b7841404   Ying Xue   net: Remove iocb ...
1047
  	return tipc_send_stream(sock, m, dsz);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1048
  }
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1049
  /* tipc_sk_finish_conn - complete the setup of a connection
b97bf3fd8   Per Liden   [TIPC] Initial merge
1050
   */
301bae56f   Jon Paul Maloy   tipc: merge struc...
1051
  static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port,
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1052
  				u32 peer_node)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1053
  {
3721e9c7c   Ying Xue   tipc: remove redu...
1054
1055
  	struct sock *sk = &tsk->sk;
  	struct net *net = sock_net(sk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
1056
  	struct tipc_msg *msg = &tsk->phdr;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1057

dadebc002   Jon Paul Maloy   tipc: eliminate p...
1058
1059
1060
1061
1062
  	msg_set_destnode(msg, peer_node);
  	msg_set_destport(msg, peer_port);
  	msg_set_type(msg, TIPC_CONN_MSG);
  	msg_set_lookup_scope(msg, 0);
  	msg_set_hdr_sz(msg, SHORT_H_SIZE);
584d24b39   Ying Xue   tipc: introduce n...
1063

2f55c4378   Ying Xue   tipc: remove unne...
1064
  	tsk->probing_intv = CONN_PROBING_INTERVAL;
301bae56f   Jon Paul Maloy   tipc: merge struc...
1065
1066
  	tsk->probing_state = TIPC_CONN_OK;
  	tsk->connected = 1;
3721e9c7c   Ying Xue   tipc: remove redu...
1067
  	sk_reset_timer(sk, &sk->sk_timer, jiffies + tsk->probing_intv);
f2f9800d4   Ying Xue   tipc: make tipc n...
1068
1069
  	tipc_node_add_conn(net, peer_node, tsk->portid, peer_port);
  	tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid);
60020e185   Jon Paul Maloy   tipc: propagate p...
1070
  	tsk->peer_caps = tipc_node_get_capabilities(net, peer_node);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1071
1072
1073
1074
1075
1076
  	if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL)
  		return;
  
  	/* Fall back to message based flow control */
  	tsk->rcv_win = FLOWCTL_MSG_WIN;
  	tsk->snd_win = FLOWCTL_MSG_WIN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1077
1078
1079
1080
1081
1082
  }
  
  /**
   * set_orig_addr - capture sender's address for received message
   * @m: descriptor for message info
   * @msg: received message header
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1083
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1084
1085
   * Note: Address is not captured if not requested by receiver.
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
1086
  static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1087
  {
342dfc306   Steffen Hurrle   net: add build-ti...
1088
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, addr, m->msg_name);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1089

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1090
  	if (addr) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
1091
1092
  		addr->family = AF_TIPC;
  		addr->addrtype = TIPC_ADDR_ID;
60085c3d0   Mathias Krause   tipc: fix info le...
1093
  		memset(&addr->addr, 0, sizeof(addr->addr));
b97bf3fd8   Per Liden   [TIPC] Initial merge
1094
1095
  		addr->addr.id.ref = msg_origport(msg);
  		addr->addr.id.node = msg_orignode(msg);
0e65967e3   Allan Stephens   tipc: cleanup var...
1096
1097
  		addr->addr.name.domain = 0;	/* could leave uninitialized */
  		addr->scope = 0;		/* could leave uninitialized */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1098
1099
1100
1101
1102
  		m->msg_namelen = sizeof(struct sockaddr_tipc);
  	}
  }
  
  /**
301bae56f   Jon Paul Maloy   tipc: merge struc...
1103
   * tipc_sk_anc_data_recv - optionally capture ancillary data for received message
b97bf3fd8   Per Liden   [TIPC] Initial merge
1104
1105
   * @m: descriptor for message info
   * @msg: received message header
301bae56f   Jon Paul Maloy   tipc: merge struc...
1106
   * @tsk: TIPC port associated with message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1107
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1108
   * Note: Ancillary data is not captured if not requested by receiver.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1109
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1110
1111
   * Returns 0 if successful, otherwise errno
   */
301bae56f   Jon Paul Maloy   tipc: merge struc...
1112
1113
  static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
  				 struct tipc_sock *tsk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1114
1115
1116
1117
  {
  	u32 anc_data[3];
  	u32 err;
  	u32 dest_type;
3546c7508   Allan Stephens   [TIPC]: Can now r...
1118
  	int has_name;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1119
1120
1121
1122
1123
1124
  	int res;
  
  	if (likely(m->msg_controllen == 0))
  		return 0;
  
  	/* Optionally capture errored message object(s) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1125
1126
1127
1128
  	err = msg ? msg_errcode(msg) : 0;
  	if (unlikely(err)) {
  		anc_data[0] = err;
  		anc_data[1] = msg_data_sz(msg);
2db9983a4   Allan Stephens   tipc: split varia...
1129
1130
  		res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1131
  			return res;
2db9983a4   Allan Stephens   tipc: split varia...
1132
1133
1134
1135
1136
1137
  		if (anc_data[1]) {
  			res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1],
  				       msg_data(msg));
  			if (res)
  				return res;
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1138
1139
1140
  	}
  
  	/* Optionally capture message destination object */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1141
1142
1143
  	dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
  	switch (dest_type) {
  	case TIPC_NAMED_MSG:
3546c7508   Allan Stephens   [TIPC]: Can now r...
1144
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1145
1146
1147
1148
1149
  		anc_data[0] = msg_nametype(msg);
  		anc_data[1] = msg_namelower(msg);
  		anc_data[2] = msg_namelower(msg);
  		break;
  	case TIPC_MCAST_MSG:
3546c7508   Allan Stephens   [TIPC]: Can now r...
1150
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1151
1152
1153
1154
1155
  		anc_data[0] = msg_nametype(msg);
  		anc_data[1] = msg_namelower(msg);
  		anc_data[2] = msg_nameupper(msg);
  		break;
  	case TIPC_CONN_MSG:
301bae56f   Jon Paul Maloy   tipc: merge struc...
1156
1157
1158
1159
  		has_name = (tsk->conn_type != 0);
  		anc_data[0] = tsk->conn_type;
  		anc_data[1] = tsk->conn_instance;
  		anc_data[2] = tsk->conn_instance;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1160
1161
  		break;
  	default:
3546c7508   Allan Stephens   [TIPC]: Can now r...
1162
  		has_name = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1163
  	}
2db9983a4   Allan Stephens   tipc: split varia...
1164
1165
1166
1167
1168
  	if (has_name) {
  		res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data);
  		if (res)
  			return res;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1169
1170
1171
  
  	return 0;
  }
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1172
  static void tipc_sk_send_ack(struct tipc_sock *tsk)
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1173
  {
f2f9800d4   Ying Xue   tipc: make tipc n...
1174
  	struct net *net = sock_net(&tsk->sk);
a6ca10944   Ying Xue   tipc: use generic...
1175
  	struct sk_buff *skb = NULL;
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1176
  	struct tipc_msg *msg;
301bae56f   Jon Paul Maloy   tipc: merge struc...
1177
1178
  	u32 peer_port = tsk_peer_port(tsk);
  	u32 dnode = tsk_peer_node(tsk);
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1179

301bae56f   Jon Paul Maloy   tipc: merge struc...
1180
  	if (!tsk->connected)
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1181
  		return;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
1182
1183
1184
  	skb = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0,
  			      dnode, tsk_own_node(tsk), peer_port,
  			      tsk->portid, TIPC_OK);
a6ca10944   Ying Xue   tipc: use generic...
1185
  	if (!skb)
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1186
  		return;
a6ca10944   Ying Xue   tipc: use generic...
1187
  	msg = buf_msg(skb);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1188
1189
1190
1191
1192
1193
1194
1195
  	msg_set_conn_ack(msg, tsk->rcv_unacked);
  	tsk->rcv_unacked = 0;
  
  	/* Adjust to and advertize the correct window limit */
  	if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL) {
  		tsk->rcv_win = tsk_adv_blocks(tsk->sk.sk_rcvbuf);
  		msg_set_adv_win(msg, tsk->rcv_win);
  	}
af9b028e2   Jon Paul Maloy   tipc: make media ...
1196
  	tipc_node_xmit_skb(net, skb, dnode, msg_link_selector(msg));
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1197
  }
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1198
  static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
9bbb4ecc6   Ying Xue   tipc: standardize...
1199
1200
1201
  {
  	struct sock *sk = sock->sk;
  	DEFINE_WAIT(wait);
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1202
  	long timeo = *timeop;
9bbb4ecc6   Ying Xue   tipc: standardize...
1203
1204
1205
1206
  	int err;
  
  	for (;;) {
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
fe8e46493   Ying Xue   tipc: avoid to un...
1207
  		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
9bbb4ecc6   Ying Xue   tipc: standardize...
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
  			if (sock->state == SS_DISCONNECTING) {
  				err = -ENOTCONN;
  				break;
  			}
  			release_sock(sk);
  			timeo = schedule_timeout(timeo);
  			lock_sock(sk);
  		}
  		err = 0;
  		if (!skb_queue_empty(&sk->sk_receive_queue))
  			break;
9bbb4ecc6   Ying Xue   tipc: standardize...
1219
1220
1221
  		err = -EAGAIN;
  		if (!timeo)
  			break;
143fe22f5   Erik Hugne   tipc: fix inconsi...
1222
1223
1224
  		err = sock_intr_errno(timeo);
  		if (signal_pending(current))
  			break;
9bbb4ecc6   Ying Xue   tipc: standardize...
1225
1226
  	}
  	finish_wait(sk_sleep(sk), &wait);
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1227
  	*timeop = timeo;
9bbb4ecc6   Ying Xue   tipc: standardize...
1228
1229
  	return err;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1230
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1231
   * tipc_recvmsg - receive packet-oriented message
b97bf3fd8   Per Liden   [TIPC] Initial merge
1232
1233
1234
   * @m: descriptor for message info
   * @buf_len: total size of user buffer area
   * @flags: receive flags
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1235
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1236
1237
1238
1239
1240
   * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages.
   * If the complete message doesn't fit in user area, truncate it.
   *
   * Returns size of returned message data, errno otherwise
   */
1b7841404   Ying Xue   net: Remove iocb ...
1241
1242
  static int tipc_recvmsg(struct socket *sock, struct msghdr *m, size_t buf_len,
  			int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1243
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1244
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1245
  	struct tipc_sock *tsk = tipc_sk(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1246
1247
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
9bbb4ecc6   Ying Xue   tipc: standardize...
1248
  	long timeo;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1249
1250
  	unsigned int sz;
  	u32 err;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1251
  	int res, hlen;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1252

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1253
  	/* Catch invalid receive requests */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1254
1255
  	if (unlikely(!buf_len))
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1256
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1257

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1258
1259
  	if (unlikely(sock->state == SS_UNCONNECTED)) {
  		res = -ENOTCONN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1260
1261
  		goto exit;
  	}
9bbb4ecc6   Ying Xue   tipc: standardize...
1262
  	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1263
  restart:
b97bf3fd8   Per Liden   [TIPC] Initial merge
1264

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1265
  	/* Look for a message in receive queue; wait if necessary */
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1266
  	res = tipc_wait_for_rcvmsg(sock, &timeo);
9bbb4ecc6   Ying Xue   tipc: standardize...
1267
1268
  	if (res)
  		goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1269

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1270
  	/* Look at first message in receive queue */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1271
  	buf = skb_peek(&sk->sk_receive_queue);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1272
1273
  	msg = buf_msg(buf);
  	sz = msg_data_sz(msg);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1274
  	hlen = msg_hdr_sz(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1275
  	err = msg_errcode(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1276
  	/* Discard an empty non-errored message & try again */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1277
  	if ((!sz) && (!err)) {
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
1278
  		tsk_advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1279
1280
1281
1282
  		goto restart;
  	}
  
  	/* Capture sender's address (optional) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1283
1284
1285
  	set_orig_addr(m, msg);
  
  	/* Capture ancillary data (optional) */
301bae56f   Jon Paul Maloy   tipc: merge struc...
1286
  	res = tipc_sk_anc_data_recv(m, msg, tsk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1287
  	if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1288
1289
1290
  		goto exit;
  
  	/* Capture message data (if valid) & compute return value (always) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1291
1292
1293
1294
1295
  	if (!err) {
  		if (unlikely(buf_len < sz)) {
  			sz = buf_len;
  			m->msg_flags |= MSG_TRUNC;
  		}
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1296
  		res = skb_copy_datagram_msg(buf, hlen, m, sz);
0232fd0ac   Allan Stephens   tipc: Allow recei...
1297
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1298
  			goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1299
1300
1301
1302
1303
1304
1305
1306
  		res = sz;
  	} else {
  		if ((sock->state == SS_READY) ||
  		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
  			res = 0;
  		else
  			res = -ECONNRESET;
  	}
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1307
1308
1309
1310
1311
1312
1313
  	if (unlikely(flags & MSG_PEEK))
  		goto exit;
  
  	if (likely(sock->state != SS_READY)) {
  		tsk->rcv_unacked += tsk_inc(tsk, hlen + sz);
  		if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4)))
  			tipc_sk_send_ack(tsk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1314
  	}
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1315
  	tsk_advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1316
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1317
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1318
1319
  	return res;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1320
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1321
   * tipc_recv_stream - receive stream-oriented data
b97bf3fd8   Per Liden   [TIPC] Initial merge
1322
1323
1324
   * @m: descriptor for message info
   * @buf_len: total size of user buffer area
   * @flags: receive flags
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1325
1326
   *
   * Used for SOCK_STREAM messages only.  If not enough data is available
b97bf3fd8   Per Liden   [TIPC] Initial merge
1327
1328
1329
1330
   * will optionally wait for more; never truncates data.
   *
   * Returns size of returned message data, errno otherwise
   */
1b7841404   Ying Xue   net: Remove iocb ...
1331
1332
  static int tipc_recv_stream(struct socket *sock, struct msghdr *m,
  			    size_t buf_len, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1333
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1334
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1335
  	struct tipc_sock *tsk = tipc_sk(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1336
1337
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
9bbb4ecc6   Ying Xue   tipc: standardize...
1338
  	long timeo;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1339
  	unsigned int sz;
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1340
  	int sz_to_copy, target, needed;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1341
  	int sz_copied = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1342
  	u32 err;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1343
  	int res = 0, hlen;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1344

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1345
  	/* Catch invalid receive attempts */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1346
1347
  	if (unlikely(!buf_len))
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1348
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1349

9bbb4ecc6   Ying Xue   tipc: standardize...
1350
  	if (unlikely(sock->state == SS_UNCONNECTED)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1351
  		res = -ENOTCONN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1352
1353
  		goto exit;
  	}
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1354
  	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
9bbb4ecc6   Ying Xue   tipc: standardize...
1355
  	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1356

617d3c7a5   Paul Gortmaker   tipc: compress ou...
1357
  restart:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1358
  	/* Look for a message in receive queue; wait if necessary */
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1359
  	res = tipc_wait_for_rcvmsg(sock, &timeo);
9bbb4ecc6   Ying Xue   tipc: standardize...
1360
1361
  	if (res)
  		goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1362

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1363
  	/* Look at first message in receive queue */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1364
  	buf = skb_peek(&sk->sk_receive_queue);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1365
1366
  	msg = buf_msg(buf);
  	sz = msg_data_sz(msg);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1367
  	hlen = msg_hdr_sz(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1368
1369
1370
  	err = msg_errcode(msg);
  
  	/* Discard an empty non-errored message & try again */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1371
  	if ((!sz) && (!err)) {
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
1372
  		tsk_advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1373
1374
1375
1376
  		goto restart;
  	}
  
  	/* Optionally capture sender's address & ancillary data of first msg */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1377
1378
  	if (sz_copied == 0) {
  		set_orig_addr(m, msg);
301bae56f   Jon Paul Maloy   tipc: merge struc...
1379
  		res = tipc_sk_anc_data_recv(m, msg, tsk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1380
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1381
1382
1383
1384
  			goto exit;
  	}
  
  	/* Capture message data (if valid) & compute return value (always) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1385
  	if (!err) {
0232fd0ac   Allan Stephens   tipc: Allow recei...
1386
  		u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1387

0232fd0ac   Allan Stephens   tipc: Allow recei...
1388
  		sz -= offset;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1389
1390
  		needed = (buf_len - sz_copied);
  		sz_to_copy = (sz <= needed) ? sz : needed;
0232fd0ac   Allan Stephens   tipc: Allow recei...
1391

10724cc7b   Jon Paul Maloy   tipc: redesign co...
1392
  		res = skb_copy_datagram_msg(buf, hlen + offset, m, sz_to_copy);
0232fd0ac   Allan Stephens   tipc: Allow recei...
1393
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1394
  			goto exit;
0232fd0ac   Allan Stephens   tipc: Allow recei...
1395

b97bf3fd8   Per Liden   [TIPC] Initial merge
1396
1397
1398
1399
  		sz_copied += sz_to_copy;
  
  		if (sz_to_copy < sz) {
  			if (!(flags & MSG_PEEK))
0232fd0ac   Allan Stephens   tipc: Allow recei...
1400
1401
  				TIPC_SKB_CB(buf)->handle =
  				(void *)(unsigned long)(offset + sz_to_copy);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1402
1403
  			goto exit;
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1404
1405
1406
1407
1408
1409
1410
1411
1412
  	} else {
  		if (sz_copied != 0)
  			goto exit; /* can't add error msg to valid data */
  
  		if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)
  			res = 0;
  		else
  			res = -ECONNRESET;
  	}
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1413
1414
1415
1416
1417
1418
1419
  	if (unlikely(flags & MSG_PEEK))
  		goto exit;
  
  	tsk->rcv_unacked += tsk_inc(tsk, hlen + sz);
  	if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4)))
  		tipc_sk_send_ack(tsk);
  	tsk_advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1420
1421
  
  	/* Loop around if more data is required */
f64f9e719   Joe Perches   net: Move && and ...
1422
1423
  	if ((sz_copied < buf_len) &&	/* didn't get all requested data */
  	    (!skb_queue_empty(&sk->sk_receive_queue) ||
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1424
  	    (sz_copied < target)) &&	/* and more is ready or required */
f64f9e719   Joe Perches   net: Move && and ...
1425
  	    (!err))			/* and haven't reached a FIN */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1426
1427
1428
  		goto restart;
  
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1429
  	release_sock(sk);
a3b0a5a9d   Allan Stephens   [TIPC]: Simplify ...
1430
  	return sz_copied ? sz_copied : res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1431
1432
1433
  }
  
  /**
f288bef46   Ying Xue   tipc: fix race/in...
1434
1435
1436
1437
1438
1439
1440
1441
1442
   * tipc_write_space - wake up thread if port congestion is released
   * @sk: socket
   */
  static void tipc_write_space(struct sock *sk)
  {
  	struct socket_wq *wq;
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
1ce0bf50a   Herbert Xu   net: Generalise w...
1443
  	if (skwq_has_sleeper(wq))
f288bef46   Ying Xue   tipc: fix race/in...
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
  		wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
  						POLLWRNORM | POLLWRBAND);
  	rcu_read_unlock();
  }
  
  /**
   * tipc_data_ready - wake up threads to indicate messages have been received
   * @sk: socket
   * @len: the length of messages
   */
676d23690   David S. Miller   net: Fix use afte...
1454
  static void tipc_data_ready(struct sock *sk)
f288bef46   Ying Xue   tipc: fix race/in...
1455
1456
1457
1458
1459
  {
  	struct socket_wq *wq;
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
1ce0bf50a   Herbert Xu   net: Generalise w...
1460
  	if (skwq_has_sleeper(wq))
f288bef46   Ying Xue   tipc: fix race/in...
1461
1462
1463
1464
  		wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
  						POLLRDNORM | POLLRDBAND);
  	rcu_read_unlock();
  }
f4195d1ea   Ying Xue   tipc: avoid packe...
1465
1466
1467
1468
  static void tipc_sock_destruct(struct sock *sk)
  {
  	__skb_queue_purge(&sk->sk_receive_queue);
  }
f288bef46   Ying Xue   tipc: fix race/in...
1469
  /**
7e6c131e1   Ying Xue   tipc: consolidate...
1470
   * filter_connect - Handle all incoming messages for a connection-based socket
58ed94424   Jon Paul Maloy   tipc: align usage...
1471
   * @tsk: TIPC socket
1186adf7d   Jon Paul Maloy   tipc: simplify me...
1472
   * @skb: pointer to message buffer. Set to NULL if buffer is consumed
7e6c131e1   Ying Xue   tipc: consolidate...
1473
   *
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1474
   * Returns true if everything ok, false otherwise
7e6c131e1   Ying Xue   tipc: consolidate...
1475
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1476
  static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
7e6c131e1   Ying Xue   tipc: consolidate...
1477
  {
58ed94424   Jon Paul Maloy   tipc: align usage...
1478
  	struct sock *sk = &tsk->sk;
f2f9800d4   Ying Xue   tipc: make tipc n...
1479
  	struct net *net = sock_net(sk);
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1480
  	struct socket *sock = sk->sk_socket;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1481
  	struct tipc_msg *hdr = buf_msg(skb);
7e6c131e1   Ying Xue   tipc: consolidate...
1482

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1483
1484
  	if (unlikely(msg_mcast(hdr)))
  		return false;
7e6c131e1   Ying Xue   tipc: consolidate...
1485
1486
1487
  
  	switch ((int)sock->state) {
  	case SS_CONNECTED:
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1488

7e6c131e1   Ying Xue   tipc: consolidate...
1489
  		/* Accept only connection-based messages sent by peer */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1490
1491
1492
1493
1494
1495
1496
1497
1498
  		if (unlikely(!tsk_peer_msg(tsk, hdr)))
  			return false;
  
  		if (unlikely(msg_errcode(hdr))) {
  			sock->state = SS_DISCONNECTING;
  			tsk->connected = 0;
  			/* Let timer expire on it's own */
  			tipc_node_remove_conn(net, tsk_peer_node(tsk),
  					      tsk->portid);
7e6c131e1   Ying Xue   tipc: consolidate...
1499
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1500
  		return true;
7e6c131e1   Ying Xue   tipc: consolidate...
1501
  	case SS_CONNECTING:
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1502

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1503
1504
1505
  		/* Accept only ACK or NACK message */
  		if (unlikely(!msg_connected(hdr)))
  			return false;
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1506

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1507
  		if (unlikely(msg_errcode(hdr))) {
584d24b39   Ying Xue   tipc: introduce n...
1508
  			sock->state = SS_DISCONNECTING;
2c8d85182   Erik Hugne   tipc: set sk_err ...
1509
  			sk->sk_err = ECONNREFUSED;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1510
  			return true;
584d24b39   Ying Xue   tipc: introduce n...
1511
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1512
  		if (unlikely(!msg_isdata(hdr))) {
584d24b39   Ying Xue   tipc: introduce n...
1513
  			sock->state = SS_DISCONNECTING;
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1514
  			sk->sk_err = EINVAL;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1515
  			return true;
584d24b39   Ying Xue   tipc: introduce n...
1516
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1517
1518
  		tipc_sk_finish_conn(tsk, msg_origport(hdr), msg_orignode(hdr));
  		msg_set_importance(&tsk->phdr, msg_importance(hdr));
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1519
  		sock->state = SS_CONNECTED;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
  		/* If 'ACK+' message, add to socket receive queue */
  		if (msg_data_sz(hdr))
  			return true;
  
  		/* If empty 'ACK-' message, wake up sleeping connect() */
  		if (waitqueue_active(sk_sleep(sk)))
  			wake_up_interruptible(sk_sleep(sk));
  
  		/* 'ACK-' message is neither accepted nor rejected: */
  		msg_set_dest_droppable(hdr, 1);
  		return false;
7e6c131e1   Ying Xue   tipc: consolidate...
1531
1532
  	case SS_LISTENING:
  	case SS_UNCONNECTED:
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1533

7e6c131e1   Ying Xue   tipc: consolidate...
1534
  		/* Accept only SYN message */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1535
1536
  		if (!msg_connected(hdr) && !(msg_errcode(hdr)))
  			return true;
7e6c131e1   Ying Xue   tipc: consolidate...
1537
1538
1539
1540
1541
1542
1543
  		break;
  	case SS_DISCONNECTING:
  		break;
  	default:
  		pr_err("Unknown socket state %u
  ", sock->state);
  	}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1544
  	return false;
7e6c131e1   Ying Xue   tipc: consolidate...
1545
1546
1547
  }
  
  /**
aba79f332   Ying Xue   tipc: byte-based ...
1548
1549
   * rcvbuf_limit - get proper overload limit of socket receive queue
   * @sk: socket
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1550
   * @skb: message
aba79f332   Ying Xue   tipc: byte-based ...
1551
   *
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1552
1553
   * For connection oriented messages, irrespective of importance,
   * default queue limit is 2 MB.
aba79f332   Ying Xue   tipc: byte-based ...
1554
   *
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1555
1556
   * For connectionless messages, queue limits are based on message
   * importance as follows:
aba79f332   Ying Xue   tipc: byte-based ...
1557
   *
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1558
1559
1560
1561
   * TIPC_LOW_IMPORTANCE       (2 MB)
   * TIPC_MEDIUM_IMPORTANCE    (4 MB)
   * TIPC_HIGH_IMPORTANCE      (8 MB)
   * TIPC_CRITICAL_IMPORTANCE  (16 MB)
aba79f332   Ying Xue   tipc: byte-based ...
1562
1563
1564
   *
   * Returns overload limit according to corresponding message importance
   */
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1565
  static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *skb)
aba79f332   Ying Xue   tipc: byte-based ...
1566
  {
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1567
1568
1569
1570
1571
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_msg *hdr = buf_msg(skb);
  
  	if (unlikely(!msg_connected(hdr)))
  		return sk->sk_rcvbuf << msg_importance(hdr);
aba79f332   Ying Xue   tipc: byte-based ...
1572

10724cc7b   Jon Paul Maloy   tipc: redesign co...
1573
1574
  	if (likely(tsk->peer_caps & TIPC_BLOCK_FLOWCTL))
  		return sk->sk_rcvbuf;
0cee6bbe0   wangweidong   tipc: remove unne...
1575

10724cc7b   Jon Paul Maloy   tipc: redesign co...
1576
  	return FLOWCTL_MSG_LIM;
aba79f332   Ying Xue   tipc: byte-based ...
1577
1578
1579
  }
  
  /**
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1580
1581
   * filter_rcv - validate incoming message
   * @sk: socket
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1582
   * @skb: pointer to message.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1583
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1584
1585
1586
   * Enqueues message on receive queue if acceptable; optionally handles
   * disconnect indication for a connected socket.
   *
1186adf7d   Jon Paul Maloy   tipc: simplify me...
1587
   * Called with socket lock already taken
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1588
   *
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1589
   * Returns true if message was added to socket receive queue, otherwise false
b97bf3fd8   Per Liden   [TIPC] Initial merge
1590
   */
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1591
1592
  static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
  		       struct sk_buff_head *xmitq)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1593
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1594
  	struct socket *sock = sk->sk_socket;
58ed94424   Jon Paul Maloy   tipc: align usage...
1595
  	struct tipc_sock *tsk = tipc_sk(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1596
1597
1598
1599
  	struct tipc_msg *hdr = buf_msg(skb);
  	unsigned int limit = rcvbuf_limit(sk, skb);
  	int err = TIPC_OK;
  	int usr = msg_user(hdr);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1600

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1601
  	if (unlikely(msg_user(hdr) == CONN_MANAGER)) {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1602
  		tipc_sk_proto_rcv(tsk, skb, xmitq);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1603
  		return false;
1186adf7d   Jon Paul Maloy   tipc: simplify me...
1604
  	}
ec8a2e562   Jon Paul Maloy   tipc: same receiv...
1605

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1606
1607
  	if (unlikely(usr == SOCK_WAKEUP)) {
  		kfree_skb(skb);
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
1608
1609
  		tsk->link_cong = 0;
  		sk->sk_write_space(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1610
  		return false;
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
1611
  	}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1612
1613
1614
1615
1616
  	/* Drop if illegal message type */
  	if (unlikely(msg_type(hdr) > TIPC_DIRECT_MSG)) {
  		kfree_skb(skb);
  		return false;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1617

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1618
1619
1620
1621
1622
1623
1624
1625
1626
  	/* Reject if wrong message type for current socket state */
  	if (unlikely(sock->state == SS_READY)) {
  		if (msg_connected(hdr)) {
  			err = TIPC_ERR_NO_PORT;
  			goto reject;
  		}
  	} else if (unlikely(!filter_connect(tsk, skb))) {
  		err = TIPC_ERR_NO_PORT;
  		goto reject;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1627
1628
1629
  	}
  
  	/* Reject message if there isn't room to queue it */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1630
1631
1632
1633
  	if (unlikely(sk_rmem_alloc_get(sk) + skb->truesize >= limit)) {
  		err = TIPC_ERR_OVERLOAD;
  		goto reject;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1634

aba79f332   Ying Xue   tipc: byte-based ...
1635
  	/* Enqueue message */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1636
1637
1638
  	TIPC_SKB_CB(skb)->handle = NULL;
  	__skb_queue_tail(&sk->sk_receive_queue, skb);
  	skb_set_owner_r(skb, sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1639

676d23690   David S. Miller   net: Fix use afte...
1640
  	sk->sk_data_ready(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1641
1642
1643
  	return true;
  
  reject:
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1644
1645
  	if (tipc_msg_reverse(tsk_own_node(tsk), &skb, err))
  		__skb_queue_tail(xmitq, skb);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1646
  	return false;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1647
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
1648

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1649
  /**
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1650
   * tipc_backlog_rcv - handle incoming message from backlog queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1651
   * @sk: socket
a6ca10944   Ying Xue   tipc: use generic...
1652
   * @skb: message
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1653
   *
e3a77561e   Jon Paul Maloy   tipc: split up fu...
1654
   * Caller must hold socket lock
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1655
1656
1657
   *
   * Returns 0
   */
a6ca10944   Ying Xue   tipc: use generic...
1658
  static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1659
  {
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1660
  	unsigned int truesize = skb->truesize;
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1661
1662
  	struct sk_buff_head xmitq;
  	u32 dnode, selector;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1663

f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1664
1665
1666
  	__skb_queue_head_init(&xmitq);
  
  	if (likely(filter_rcv(sk, skb, &xmitq))) {
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1667
  		atomic_add(truesize, &tipc_sk(sk)->dupl_rcvcnt);
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
  		return 0;
  	}
  
  	if (skb_queue_empty(&xmitq))
  		return 0;
  
  	/* Send response/rejected message */
  	skb = __skb_dequeue(&xmitq);
  	dnode = msg_destnode(buf_msg(skb));
  	selector = msg_origport(buf_msg(skb));
  	tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1679
1680
1681
1682
  	return 0;
  }
  
  /**
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1683
1684
1685
1686
1687
   * tipc_sk_enqueue - extract all buffers with destination 'dport' from
   *                   inputq and try adding them to socket or backlog queue
   * @inputq: list of incoming buffers with potentially different destinations
   * @sk: socket where the buffers should be enqueued
   * @dport: port number for the socket
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1688
1689
   *
   * Caller must hold socket lock
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1690
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1691
  static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1692
  			    u32 dport, struct sk_buff_head *xmitq)
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1693
  {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1694
1695
  	unsigned long time_limit = jiffies + 2;
  	struct sk_buff *skb;
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1696
1697
  	unsigned int lim;
  	atomic_t *dcnt;
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1698
  	u32 onode;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1699
1700
  
  	while (skb_queue_len(inputq)) {
51a00daf7   Jon Paul Maloy   tipc: fix bug in ...
1701
  		if (unlikely(time_after_eq(jiffies, time_limit)))
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1702
  			return;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1703
1704
  		skb = tipc_skb_dequeue(inputq, dport);
  		if (unlikely(!skb))
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1705
1706
1707
  			return;
  
  		/* Add message directly to receive queue if possible */
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1708
  		if (!sock_owned_by_user(sk)) {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1709
  			filter_rcv(sk, skb, xmitq);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1710
  			continue;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1711
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1712
1713
  
  		/* Try backlog, compensating for double-counted bytes */
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1714
  		dcnt = &tipc_sk(sk)->dupl_rcvcnt;
7c8bcfb12   Jon Paul Maloy   tipc: re-enable c...
1715
  		if (!sk->sk_backlog.len)
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1716
1717
1718
1719
  			atomic_set(dcnt, 0);
  		lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt);
  		if (likely(!sk_add_backlog(sk, skb, lim)))
  			continue;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1720
1721
  
  		/* Overload => reject message back to sender */
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1722
1723
1724
  		onode = tipc_own_addr(sock_net(sk));
  		if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD))
  			__skb_queue_tail(xmitq, skb);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1725
  		break;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1726
  	}
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1727
1728
1729
  }
  
  /**
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1730
1731
1732
1733
   * tipc_sk_rcv - handle a chain of incoming buffers
   * @inputq: buffer list containing the buffers
   * Consumes all buffers in list until inputq is empty
   * Note: may be called in multiple threads referring to the same queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1734
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1735
  void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1736
  {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1737
  	struct sk_buff_head xmitq;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1738
  	u32 dnode, dport = 0;
9871b27f6   Erik Hugne   tipc: fix random ...
1739
  	int err;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1740
  	struct tipc_sock *tsk;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1741
  	struct sock *sk;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1742
  	struct sk_buff *skb;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1743

f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1744
  	__skb_queue_head_init(&xmitq);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1745
  	while (skb_queue_len(inputq)) {
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1746
1747
  		dport = tipc_skb_peek_port(inputq, dport);
  		tsk = tipc_sk_lookup(net, dport);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1748

c637c1035   Jon Paul Maloy   tipc: resolve rac...
1749
1750
1751
  		if (likely(tsk)) {
  			sk = &tsk->sk;
  			if (likely(spin_trylock_bh(&sk->sk_lock.slock))) {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1752
  				tipc_sk_enqueue(inputq, sk, dport, &xmitq);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1753
  				spin_unlock_bh(&sk->sk_lock.slock);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1754
  			}
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1755
1756
1757
1758
1759
  			/* Send pending response/rejected messages, if any */
  			while ((skb = __skb_dequeue(&xmitq))) {
  				dnode = msg_destnode(buf_msg(skb));
  				tipc_node_xmit_skb(net, skb, dnode, dport);
  			}
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1760
  			sock_put(sk);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1761
  			continue;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1762
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
  
  		/* No destination socket => dequeue skb if still there */
  		skb = tipc_skb_dequeue(inputq, dport);
  		if (!skb)
  			return;
  
  		/* Try secondary lookup if unresolved named message */
  		err = TIPC_ERR_NO_PORT;
  		if (tipc_msg_lookup_dest(net, skb, &err))
  			goto xmit;
  
  		/* Prepare for message rejection */
  		if (!tipc_msg_reverse(tipc_own_addr(net), &skb, err))
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1776
  			continue;
e3a77561e   Jon Paul Maloy   tipc: split up fu...
1777
  xmit:
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1778
  		dnode = msg_destnode(buf_msg(skb));
af9b028e2   Jon Paul Maloy   tipc: make media ...
1779
  		tipc_node_xmit_skb(net, skb, dnode, dport);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1780
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1781
  }
78eb3a537   Ying Xue   tipc: standardize...
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
  static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
  {
  	struct sock *sk = sock->sk;
  	DEFINE_WAIT(wait);
  	int done;
  
  	do {
  		int err = sock_error(sk);
  		if (err)
  			return err;
  		if (!*timeo_p)
  			return -ETIMEDOUT;
  		if (signal_pending(current))
  			return sock_intr_errno(*timeo_p);
  
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  		done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING);
  		finish_wait(sk_sleep(sk), &wait);
  	} while (!done);
  	return 0;
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
1803
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1804
   * tipc_connect - establish a connection to another TIPC port
b97bf3fd8   Per Liden   [TIPC] Initial merge
1805
1806
1807
   * @sock: socket structure
   * @dest: socket address for destination port
   * @destlen: size of socket address data structure
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1808
   * @flags: file-related flags associated with socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
1809
1810
1811
   *
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1812
1813
  static int tipc_connect(struct socket *sock, struct sockaddr *dest,
  			int destlen, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1814
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1815
  	struct sock *sk = sock->sk;
f2f8036e3   Erik Hugne   tipc: add support...
1816
  	struct tipc_sock *tsk = tipc_sk(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1817
1818
  	struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
  	struct msghdr m = {NULL,};
f2f8036e3   Erik Hugne   tipc: add support...
1819
  	long timeout = (flags & O_NONBLOCK) ? 0 : tsk->conn_timeout;
78eb3a537   Ying Xue   tipc: standardize...
1820
  	socket_state previous;
f2f8036e3   Erik Hugne   tipc: add support...
1821
  	int res = 0;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1822

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1823
  	lock_sock(sk);
f2f8036e3   Erik Hugne   tipc: add support...
1824
  	/* DGRAM/RDM connect(), just save the destaddr */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1825
  	if (sock->state == SS_READY) {
f2f8036e3   Erik Hugne   tipc: add support...
1826
1827
1828
  		if (dst->family == AF_UNSPEC) {
  			memset(&tsk->remote, 0, sizeof(struct sockaddr_tipc));
  			tsk->connected = 0;
610600c8c   Sasha Levin   tipc: validate le...
1829
1830
  		} else if (destlen != sizeof(struct sockaddr_tipc)) {
  			res = -EINVAL;
f2f8036e3   Erik Hugne   tipc: add support...
1831
1832
1833
1834
  		} else {
  			memcpy(&tsk->remote, dest, destlen);
  			tsk->connected = 1;
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1835
1836
  		goto exit;
  	}
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1837

b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1838
1839
1840
1841
1842
1843
  	/*
  	 * Reject connection attempt using multicast address
  	 *
  	 * Note: send_msg() validates the rest of the address fields,
  	 *       so there's no need to do it here
  	 */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1844
1845
1846
1847
  	if (dst->addrtype == TIPC_ADDR_MCAST) {
  		res = -EINVAL;
  		goto exit;
  	}
78eb3a537   Ying Xue   tipc: standardize...
1848
  	previous = sock->state;
584d24b39   Ying Xue   tipc: introduce n...
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
  	switch (sock->state) {
  	case SS_UNCONNECTED:
  		/* Send a 'SYN-' to destination */
  		m.msg_name = dest;
  		m.msg_namelen = destlen;
  
  		/* If connect is in non-blocking case, set MSG_DONTWAIT to
  		 * indicate send_msg() is never blocked.
  		 */
  		if (!timeout)
  			m.msg_flags = MSG_DONTWAIT;
39a0295f9   Ying Xue   tipc: Don't use i...
1860
  		res = __tipc_sendmsg(sock, &m, 0);
584d24b39   Ying Xue   tipc: introduce n...
1861
1862
1863
1864
1865
1866
1867
1868
  		if ((res < 0) && (res != -EWOULDBLOCK))
  			goto exit;
  
  		/* Just entered SS_CONNECTING state; the only
  		 * difference is that return value in non-blocking
  		 * case is EINPROGRESS, rather than EALREADY.
  		 */
  		res = -EINPROGRESS;
584d24b39   Ying Xue   tipc: introduce n...
1869
  	case SS_CONNECTING:
78eb3a537   Ying Xue   tipc: standardize...
1870
1871
1872
1873
1874
1875
1876
  		if (previous == SS_CONNECTING)
  			res = -EALREADY;
  		if (!timeout)
  			goto exit;
  		timeout = msecs_to_jiffies(timeout);
  		/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
  		res = tipc_wait_for_connect(sock, &timeout);
584d24b39   Ying Xue   tipc: introduce n...
1877
1878
1879
1880
1881
1882
  		break;
  	case SS_CONNECTED:
  		res = -EISCONN;
  		break;
  	default:
  		res = -EINVAL;
78eb3a537   Ying Xue   tipc: standardize...
1883
  		break;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1884
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1885
1886
  exit:
  	release_sock(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1887
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1888
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1889
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1890
   * tipc_listen - allow socket to listen for incoming connections
b97bf3fd8   Per Liden   [TIPC] Initial merge
1891
1892
   * @sock: socket structure
   * @len: (unused)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1893
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1894
1895
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1896
  static int tipc_listen(struct socket *sock, int len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1897
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1898
1899
1900
1901
  	struct sock *sk = sock->sk;
  	int res;
  
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1902

245f3d342   Ying Xue   tipc: Simplify pr...
1903
  	if (sock->state != SS_UNCONNECTED)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1904
1905
1906
1907
1908
1909
1910
1911
  		res = -EINVAL;
  	else {
  		sock->state = SS_LISTENING;
  		res = 0;
  	}
  
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1912
  }
6398e23cd   Ying Xue   tipc: standardize...
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
  static int tipc_wait_for_accept(struct socket *sock, long timeo)
  {
  	struct sock *sk = sock->sk;
  	DEFINE_WAIT(wait);
  	int err;
  
  	/* True wake-one mechanism for incoming connections: only
  	 * one process gets woken up, not the 'whole herd'.
  	 * Since we do not 'race & poll' for established sockets
  	 * anymore, the common case will execute the loop only once.
  	*/
  	for (;;) {
  		prepare_to_wait_exclusive(sk_sleep(sk), &wait,
  					  TASK_INTERRUPTIBLE);
fe8e46493   Ying Xue   tipc: avoid to un...
1927
  		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
6398e23cd   Ying Xue   tipc: standardize...
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
  			release_sock(sk);
  			timeo = schedule_timeout(timeo);
  			lock_sock(sk);
  		}
  		err = 0;
  		if (!skb_queue_empty(&sk->sk_receive_queue))
  			break;
  		err = -EINVAL;
  		if (sock->state != SS_LISTENING)
  			break;
6398e23cd   Ying Xue   tipc: standardize...
1938
1939
1940
  		err = -EAGAIN;
  		if (!timeo)
  			break;
143fe22f5   Erik Hugne   tipc: fix inconsi...
1941
1942
1943
  		err = sock_intr_errno(timeo);
  		if (signal_pending(current))
  			break;
6398e23cd   Ying Xue   tipc: standardize...
1944
1945
1946
1947
  	}
  	finish_wait(sk_sleep(sk), &wait);
  	return err;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1948
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1949
   * tipc_accept - wait for connection request
b97bf3fd8   Per Liden   [TIPC] Initial merge
1950
1951
1952
   * @sock: listening socket
   * @newsock: new socket that is to be connected
   * @flags: file-related flags associated with socket
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1953
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1954
1955
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1956
  static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1957
  {
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1958
  	struct sock *new_sk, *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1959
  	struct sk_buff *buf;
301bae56f   Jon Paul Maloy   tipc: merge struc...
1960
  	struct tipc_sock *new_tsock;
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1961
  	struct tipc_msg *msg;
6398e23cd   Ying Xue   tipc: standardize...
1962
  	long timeo;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1963
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1964

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1965
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1966

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1967
1968
  	if (sock->state != SS_LISTENING) {
  		res = -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1969
1970
  		goto exit;
  	}
6398e23cd   Ying Xue   tipc: standardize...
1971
1972
1973
1974
  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
  	res = tipc_wait_for_accept(sock, timeo);
  	if (res)
  		goto exit;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1975
1976
  
  	buf = skb_peek(&sk->sk_receive_queue);
c5fa7b3cf   Ying Xue   tipc: introduce n...
1977
  	res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1978
1979
  	if (res)
  		goto exit;
fdd75ea8d   Stephen Smalley   net/tipc: initial...
1980
  	security_sk_clone(sock->sk, new_sock->sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1981

0fef8f205   Paul Gortmaker   tipc: refactor ac...
1982
  	new_sk = new_sock->sk;
301bae56f   Jon Paul Maloy   tipc: merge struc...
1983
  	new_tsock = tipc_sk(new_sk);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1984
  	msg = buf_msg(buf);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1985

0fef8f205   Paul Gortmaker   tipc: refactor ac...
1986
1987
1988
1989
1990
1991
1992
  	/* we lock on new_sk; but lockdep sees the lock on sk */
  	lock_sock_nested(new_sk, SINGLE_DEPTH_NESTING);
  
  	/*
  	 * Reject any stray messages received by new socket
  	 * before the socket lock was taken (very, very unlikely)
  	 */
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
1993
  	tsk_rej_rx_queue(new_sk);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1994
1995
  
  	/* Connect new socket to it's peer */
301bae56f   Jon Paul Maloy   tipc: merge struc...
1996
  	tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1997
  	new_sock->state = SS_CONNECTED;
301bae56f   Jon Paul Maloy   tipc: merge struc...
1998
  	tsk_set_importance(new_tsock, msg_importance(msg));
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1999
  	if (msg_named(msg)) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
2000
2001
  		new_tsock->conn_type = msg_nametype(msg);
  		new_tsock->conn_instance = msg_nameinst(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2002
  	}
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2003
2004
2005
2006
2007
2008
2009
  
  	/*
  	 * Respond to 'SYN-' by discarding it & returning 'ACK'-.
  	 * Respond to 'SYN+' by queuing it on new socket.
  	 */
  	if (!msg_data_sz(msg)) {
  		struct msghdr m = {NULL,};
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
2010
  		tsk_advance_rx_queue(sk);
39a0295f9   Ying Xue   tipc: Don't use i...
2011
  		__tipc_send_stream(new_sock, &m, 0);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2012
2013
2014
  	} else {
  		__skb_dequeue(&sk->sk_receive_queue);
  		__skb_queue_head(&new_sk->sk_receive_queue, buf);
aba79f332   Ying Xue   tipc: byte-based ...
2015
  		skb_set_owner_r(buf, new_sk);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2016
2017
  	}
  	release_sock(new_sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2018
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2019
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2020
2021
2022
2023
  	return res;
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
2024
   * tipc_shutdown - shutdown socket connection
b97bf3fd8   Per Liden   [TIPC] Initial merge
2025
   * @sock: socket structure
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
2026
   * @how: direction to close (must be SHUT_RDWR)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2027
2028
   *
   * Terminates connection (if necessary), then purges socket's receive queue.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2029
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
2030
2031
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
2032
  static int tipc_shutdown(struct socket *sock, int how)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2033
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2034
  	struct sock *sk = sock->sk;
f2f9800d4   Ying Xue   tipc: make tipc n...
2035
  	struct net *net = sock_net(sk);
58ed94424   Jon Paul Maloy   tipc: align usage...
2036
  	struct tipc_sock *tsk = tipc_sk(sk);
a6ca10944   Ying Xue   tipc: use generic...
2037
  	struct sk_buff *skb;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
2038
2039
2040
2041
  	u32 dnode = tsk_peer_node(tsk);
  	u32 dport = tsk_peer_port(tsk);
  	u32 onode = tipc_own_addr(net);
  	u32 oport = tsk->portid;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2042
  	int res;
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
2043
2044
  	if (how != SHUT_RDWR)
  		return -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2045

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2046
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2047
2048
  
  	switch (sock->state) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2049
  	case SS_CONNECTING:
b97bf3fd8   Per Liden   [TIPC] Initial merge
2050
  	case SS_CONNECTED:
b97bf3fd8   Per Liden   [TIPC] Initial merge
2051
  restart:
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
2052
  		dnode = tsk_peer_node(tsk);
617d3c7a5   Paul Gortmaker   tipc: compress ou...
2053
  		/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
a6ca10944   Ying Xue   tipc: use generic...
2054
2055
2056
2057
  		skb = __skb_dequeue(&sk->sk_receive_queue);
  		if (skb) {
  			if (TIPC_SKB_CB(skb)->handle != NULL) {
  				kfree_skb(skb);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2058
2059
  				goto restart;
  			}
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
2060
  			tipc_sk_respond(sk, skb, TIPC_CONN_SHUTDOWN);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2061
  		} else {
c5898636c   Jon Paul Maloy   tipc: reduce usag...
2062
  			skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
80e44c222   Jon Paul Maloy   tipc: eliminate f...
2063
  					      TIPC_CONN_MSG, SHORT_H_SIZE,
cda3696d3   Jon Paul Maloy   tipc: clean up so...
2064
2065
  					      0, dnode, onode, dport, oport,
  					      TIPC_CONN_SHUTDOWN);
d2fbdf76b   Vegard Nossum   tipc: fix NULL po...
2066
2067
  			if (skb)
  				tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2068
  		}
301bae56f   Jon Paul Maloy   tipc: merge struc...
2069
  		tsk->connected = 0;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2070
  		sock->state = SS_DISCONNECTING;
f2f9800d4   Ying Xue   tipc: make tipc n...
2071
  		tipc_node_remove_conn(net, dnode, tsk->portid);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2072
2073
2074
  		/* fall through */
  
  	case SS_DISCONNECTING:
750311510   Ying Xue   tipc: wake up all...
2075
  		/* Discard any unreceived messages */
57467e562   Ying Xue   tipc: eliminate d...
2076
  		__skb_queue_purge(&sk->sk_receive_queue);
750311510   Ying Xue   tipc: wake up all...
2077
2078
2079
  
  		/* Wake up anyone sleeping in poll */
  		sk->sk_state_change(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2080
2081
2082
2083
2084
2085
  		res = 0;
  		break;
  
  	default:
  		res = -ENOTCONN;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2086
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2087
2088
  	return res;
  }
f2f2a96a2   Ying Xue   tipc: feed tipc s...
2089
  static void tipc_sk_timeout(unsigned long data)
572890158   Jon Paul Maloy   tipc: clean up so...
2090
  {
f2f2a96a2   Ying Xue   tipc: feed tipc s...
2091
2092
  	struct tipc_sock *tsk = (struct tipc_sock *)data;
  	struct sock *sk = &tsk->sk;
a6ca10944   Ying Xue   tipc: use generic...
2093
  	struct sk_buff *skb = NULL;
572890158   Jon Paul Maloy   tipc: clean up so...
2094
  	u32 peer_port, peer_node;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
2095
  	u32 own_node = tsk_own_node(tsk);
572890158   Jon Paul Maloy   tipc: clean up so...
2096

6c9808ce0   Jon Paul Maloy   tipc: remove port...
2097
  	bh_lock_sock(sk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
2098
  	if (!tsk->connected) {
6c9808ce0   Jon Paul Maloy   tipc: remove port...
2099
2100
  		bh_unlock_sock(sk);
  		goto exit;
572890158   Jon Paul Maloy   tipc: clean up so...
2101
  	}
301bae56f   Jon Paul Maloy   tipc: merge struc...
2102
2103
  	peer_port = tsk_peer_port(tsk);
  	peer_node = tsk_peer_node(tsk);
572890158   Jon Paul Maloy   tipc: clean up so...
2104

301bae56f   Jon Paul Maloy   tipc: merge struc...
2105
  	if (tsk->probing_state == TIPC_CONN_PROBING) {
b3be5e3e7   Erik Hugne   tipc: disconnect ...
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
  		if (!sock_owned_by_user(sk)) {
  			sk->sk_socket->state = SS_DISCONNECTING;
  			tsk->connected = 0;
  			tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
  					      tsk_peer_port(tsk));
  			sk->sk_state_change(sk);
  		} else {
  			/* Try again later */
  			sk_reset_timer(sk, &sk->sk_timer, (HZ / 20));
  		}
572890158   Jon Paul Maloy   tipc: clean up so...
2116
  	} else {
c5898636c   Jon Paul Maloy   tipc: reduce usag...
2117
2118
  		skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE,
  				      INT_H_SIZE, 0, peer_node, own_node,
f2f2a96a2   Ying Xue   tipc: feed tipc s...
2119
  				      peer_port, tsk->portid, TIPC_OK);
301bae56f   Jon Paul Maloy   tipc: merge struc...
2120
  		tsk->probing_state = TIPC_CONN_PROBING;
3721e9c7c   Ying Xue   tipc: remove redu...
2121
  		sk_reset_timer(sk, &sk->sk_timer, jiffies + tsk->probing_intv);
572890158   Jon Paul Maloy   tipc: clean up so...
2122
2123
  	}
  	bh_unlock_sock(sk);
a6ca10944   Ying Xue   tipc: use generic...
2124
  	if (skb)
af9b028e2   Jon Paul Maloy   tipc: make media ...
2125
  		tipc_node_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid);
6c9808ce0   Jon Paul Maloy   tipc: remove port...
2126
  exit:
07f6c4bc0   Ying Xue   tipc: convert tip...
2127
  	sock_put(sk);
572890158   Jon Paul Maloy   tipc: clean up so...
2128
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
2129
  static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2130
2131
  			   struct tipc_name_seq const *seq)
  {
f2f9800d4   Ying Xue   tipc: make tipc n...
2132
  	struct net *net = sock_net(&tsk->sk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2133
2134
  	struct publication *publ;
  	u32 key;
301bae56f   Jon Paul Maloy   tipc: merge struc...
2135
  	if (tsk->connected)
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2136
  		return -EINVAL;
07f6c4bc0   Ying Xue   tipc: convert tip...
2137
2138
  	key = tsk->portid + tsk->pub_count + 1;
  	if (key == tsk->portid)
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2139
  		return -EADDRINUSE;
f2f9800d4   Ying Xue   tipc: make tipc n...
2140
  	publ = tipc_nametbl_publish(net, seq->type, seq->lower, seq->upper,
07f6c4bc0   Ying Xue   tipc: convert tip...
2141
  				    scope, tsk->portid, key);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2142
2143
  	if (unlikely(!publ))
  		return -EINVAL;
301bae56f   Jon Paul Maloy   tipc: merge struc...
2144
2145
2146
  	list_add(&publ->pport_list, &tsk->publications);
  	tsk->pub_count++;
  	tsk->published = 1;
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2147
2148
  	return 0;
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
2149
  static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2150
2151
  			    struct tipc_name_seq const *seq)
  {
f2f9800d4   Ying Xue   tipc: make tipc n...
2152
  	struct net *net = sock_net(&tsk->sk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2153
2154
2155
  	struct publication *publ;
  	struct publication *safe;
  	int rc = -EINVAL;
301bae56f   Jon Paul Maloy   tipc: merge struc...
2156
  	list_for_each_entry_safe(publ, safe, &tsk->publications, pport_list) {
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2157
2158
2159
2160
2161
2162
2163
2164
2165
  		if (seq) {
  			if (publ->scope != scope)
  				continue;
  			if (publ->type != seq->type)
  				continue;
  			if (publ->lower != seq->lower)
  				continue;
  			if (publ->upper != seq->upper)
  				break;
f2f9800d4   Ying Xue   tipc: make tipc n...
2166
  			tipc_nametbl_withdraw(net, publ->type, publ->lower,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2167
2168
2169
2170
  					      publ->ref, publ->key);
  			rc = 0;
  			break;
  		}
f2f9800d4   Ying Xue   tipc: make tipc n...
2171
  		tipc_nametbl_withdraw(net, publ->type, publ->lower,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2172
2173
2174
  				      publ->ref, publ->key);
  		rc = 0;
  	}
301bae56f   Jon Paul Maloy   tipc: merge struc...
2175
2176
  	if (list_empty(&tsk->publications))
  		tsk->published = 0;
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2177
2178
  	return rc;
  }
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2179
2180
2181
  /* tipc_sk_reinit: set non-zero address in all existing sockets
   *                 when we go from standalone to network mode.
   */
e05b31f4b   Ying Xue   tipc: make tipc s...
2182
  void tipc_sk_reinit(struct net *net)
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2183
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2184
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
07f6c4bc0   Ying Xue   tipc: convert tip...
2185
2186
2187
  	const struct bucket_table *tbl;
  	struct rhash_head *pos;
  	struct tipc_sock *tsk;
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2188
  	struct tipc_msg *msg;
07f6c4bc0   Ying Xue   tipc: convert tip...
2189
  	int i;
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2190

07f6c4bc0   Ying Xue   tipc: convert tip...
2191
  	rcu_read_lock();
e05b31f4b   Ying Xue   tipc: make tipc s...
2192
  	tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht);
07f6c4bc0   Ying Xue   tipc: convert tip...
2193
2194
2195
2196
  	for (i = 0; i < tbl->size; i++) {
  		rht_for_each_entry_rcu(tsk, pos, tbl, i, node) {
  			spin_lock_bh(&tsk->sk.sk_lock.slock);
  			msg = &tsk->phdr;
347475395   Ying Xue   tipc: make tipc n...
2197
2198
  			msg_set_prevnode(msg, tn->own_addr);
  			msg_set_orignode(msg, tn->own_addr);
07f6c4bc0   Ying Xue   tipc: convert tip...
2199
2200
  			spin_unlock_bh(&tsk->sk.sk_lock.slock);
  		}
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2201
  	}
07f6c4bc0   Ying Xue   tipc: convert tip...
2202
  	rcu_read_unlock();
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2203
  }
e05b31f4b   Ying Xue   tipc: make tipc s...
2204
  static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2205
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2206
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
07f6c4bc0   Ying Xue   tipc: convert tip...
2207
  	struct tipc_sock *tsk;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2208

07f6c4bc0   Ying Xue   tipc: convert tip...
2209
  	rcu_read_lock();
6cca7289d   Herbert Xu   tipc: Use inlined...
2210
  	tsk = rhashtable_lookup_fast(&tn->sk_rht, &portid, tsk_rht_params);
07f6c4bc0   Ying Xue   tipc: convert tip...
2211
2212
2213
  	if (tsk)
  		sock_hold(&tsk->sk);
  	rcu_read_unlock();
808d90f9c   Jon Paul Maloy   tipc: remove file...
2214

07f6c4bc0   Ying Xue   tipc: convert tip...
2215
  	return tsk;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2216
  }
07f6c4bc0   Ying Xue   tipc: convert tip...
2217
  static int tipc_sk_insert(struct tipc_sock *tsk)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2218
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2219
2220
2221
  	struct sock *sk = &tsk->sk;
  	struct net *net = sock_net(sk);
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
07f6c4bc0   Ying Xue   tipc: convert tip...
2222
2223
  	u32 remaining = (TIPC_MAX_PORT - TIPC_MIN_PORT) + 1;
  	u32 portid = prandom_u32() % remaining + TIPC_MIN_PORT;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2224

07f6c4bc0   Ying Xue   tipc: convert tip...
2225
2226
2227
2228
2229
2230
  	while (remaining--) {
  		portid++;
  		if ((portid < TIPC_MIN_PORT) || (portid > TIPC_MAX_PORT))
  			portid = TIPC_MIN_PORT;
  		tsk->portid = portid;
  		sock_hold(&tsk->sk);
6cca7289d   Herbert Xu   tipc: Use inlined...
2231
2232
  		if (!rhashtable_lookup_insert_fast(&tn->sk_rht, &tsk->node,
  						   tsk_rht_params))
07f6c4bc0   Ying Xue   tipc: convert tip...
2233
2234
  			return 0;
  		sock_put(&tsk->sk);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2235
  	}
07f6c4bc0   Ying Xue   tipc: convert tip...
2236
  	return -1;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2237
  }
07f6c4bc0   Ying Xue   tipc: convert tip...
2238
  static void tipc_sk_remove(struct tipc_sock *tsk)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2239
  {
07f6c4bc0   Ying Xue   tipc: convert tip...
2240
  	struct sock *sk = &tsk->sk;
e05b31f4b   Ying Xue   tipc: make tipc s...
2241
  	struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2242

6cca7289d   Herbert Xu   tipc: Use inlined...
2243
  	if (!rhashtable_remove_fast(&tn->sk_rht, &tsk->node, tsk_rht_params)) {
07f6c4bc0   Ying Xue   tipc: convert tip...
2244
2245
  		WARN_ON(atomic_read(&sk->sk_refcnt) == 1);
  		__sock_put(sk);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2246
  	}
808d90f9c   Jon Paul Maloy   tipc: remove file...
2247
  }
6cca7289d   Herbert Xu   tipc: Use inlined...
2248
2249
2250
2251
2252
  static const struct rhashtable_params tsk_rht_params = {
  	.nelem_hint = 192,
  	.head_offset = offsetof(struct tipc_sock, node),
  	.key_offset = offsetof(struct tipc_sock, portid),
  	.key_len = sizeof(u32), /* portid */
6cca7289d   Herbert Xu   tipc: Use inlined...
2253
2254
  	.max_size = 1048576,
  	.min_size = 256,
b5e2c150a   Thomas Graf   rhashtable: Disab...
2255
  	.automatic_shrinking = true,
6cca7289d   Herbert Xu   tipc: Use inlined...
2256
  };
e05b31f4b   Ying Xue   tipc: make tipc s...
2257
  int tipc_sk_rht_init(struct net *net)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2258
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2259
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
6cca7289d   Herbert Xu   tipc: Use inlined...
2260
2261
  
  	return rhashtable_init(&tn->sk_rht, &tsk_rht_params);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2262
  }
e05b31f4b   Ying Xue   tipc: make tipc s...
2263
  void tipc_sk_rht_destroy(struct net *net)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2264
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2265
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
07f6c4bc0   Ying Xue   tipc: convert tip...
2266
2267
  	/* Wait for socket readers to complete */
  	synchronize_net();
808d90f9c   Jon Paul Maloy   tipc: remove file...
2268

e05b31f4b   Ying Xue   tipc: make tipc s...
2269
  	rhashtable_destroy(&tn->sk_rht);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2270
2271
2272
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
2273
   * tipc_setsockopt - set socket option
b97bf3fd8   Per Liden   [TIPC] Initial merge
2274
2275
2276
2277
2278
   * @sock: socket structure
   * @lvl: option level
   * @opt: option identifier
   * @ov: pointer to new option value
   * @ol: length of option value
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2279
2280
   *
   * For stream sockets only, accepts and ignores all IPPROTO_TCP options
b97bf3fd8   Per Liden   [TIPC] Initial merge
2281
   * (to ease compatibility).
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2282
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
2283
2284
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
2285
2286
  static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
  			   char __user *ov, unsigned int ol)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2287
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2288
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
2289
  	struct tipc_sock *tsk = tipc_sk(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2290
2291
  	u32 value;
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2292
2293
  	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
  		return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2294
2295
2296
2297
  	if (lvl != SOL_TIPC)
  		return -ENOPROTOOPT;
  	if (ol < sizeof(value))
  		return -EINVAL;
2db9983a4   Allan Stephens   tipc: split varia...
2298
2299
  	res = get_user(value, (u32 __user *)ov);
  	if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2300
  		return res;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2301
  	lock_sock(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2302

b97bf3fd8   Per Liden   [TIPC] Initial merge
2303
2304
  	switch (opt) {
  	case TIPC_IMPORTANCE:
301bae56f   Jon Paul Maloy   tipc: merge struc...
2305
  		res = tsk_set_importance(tsk, value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2306
2307
2308
  		break;
  	case TIPC_SRC_DROPPABLE:
  		if (sock->type != SOCK_STREAM)
301bae56f   Jon Paul Maloy   tipc: merge struc...
2309
  			tsk_set_unreliable(tsk, value);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2310
  		else
b97bf3fd8   Per Liden   [TIPC] Initial merge
2311
2312
2313
  			res = -ENOPROTOOPT;
  		break;
  	case TIPC_DEST_DROPPABLE:
301bae56f   Jon Paul Maloy   tipc: merge struc...
2314
  		tsk_set_unreturnable(tsk, value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2315
2316
  		break;
  	case TIPC_CONN_TIMEOUT:
a0f40f02e   Allan Stephens   tipc: Prevent rou...
2317
  		tipc_sk(sk)->conn_timeout = value;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2318
  		/* no need to set "res", since already 0 at this point */
b97bf3fd8   Per Liden   [TIPC] Initial merge
2319
2320
2321
2322
  		break;
  	default:
  		res = -EINVAL;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2323
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2324
2325
2326
2327
  	return res;
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
2328
   * tipc_getsockopt - get socket option
b97bf3fd8   Per Liden   [TIPC] Initial merge
2329
2330
2331
2332
2333
   * @sock: socket structure
   * @lvl: option level
   * @opt: option identifier
   * @ov: receptacle for option value
   * @ol: receptacle for length of option value
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2334
2335
   *
   * For stream sockets only, returns 0 length result for all IPPROTO_TCP options
b97bf3fd8   Per Liden   [TIPC] Initial merge
2336
   * (to ease compatibility).
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2337
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
2338
2339
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
2340
2341
  static int tipc_getsockopt(struct socket *sock, int lvl, int opt,
  			   char __user *ov, int __user *ol)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2342
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2343
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
2344
  	struct tipc_sock *tsk = tipc_sk(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2345
  	int len;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2346
  	u32 value;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2347
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2348

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2349
2350
  	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
  		return put_user(0, ol);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2351
2352
  	if (lvl != SOL_TIPC)
  		return -ENOPROTOOPT;
2db9983a4   Allan Stephens   tipc: split varia...
2353
2354
  	res = get_user(len, ol);
  	if (res)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2355
  		return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2356

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2357
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2358
2359
2360
  
  	switch (opt) {
  	case TIPC_IMPORTANCE:
301bae56f   Jon Paul Maloy   tipc: merge struc...
2361
  		value = tsk_importance(tsk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2362
2363
  		break;
  	case TIPC_SRC_DROPPABLE:
301bae56f   Jon Paul Maloy   tipc: merge struc...
2364
  		value = tsk_unreliable(tsk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2365
2366
  		break;
  	case TIPC_DEST_DROPPABLE:
301bae56f   Jon Paul Maloy   tipc: merge struc...
2367
  		value = tsk_unreturnable(tsk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2368
2369
  		break;
  	case TIPC_CONN_TIMEOUT:
301bae56f   Jon Paul Maloy   tipc: merge struc...
2370
  		value = tsk->conn_timeout;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2371
  		/* no need to set "res", since already 0 at this point */
b97bf3fd8   Per Liden   [TIPC] Initial merge
2372
  		break;
0e65967e3   Allan Stephens   tipc: cleanup var...
2373
  	case TIPC_NODE_RECVQ_DEPTH:
9da3d4758   Ying Xue   tipc: eliminate a...
2374
  		value = 0; /* was tipc_queue_size, now obsolete */
6650613d3   oscar.medina@motorola.com   tipc: Add socket ...
2375
  		break;
0e65967e3   Allan Stephens   tipc: cleanup var...
2376
  	case TIPC_SOCK_RECVQ_DEPTH:
6650613d3   oscar.medina@motorola.com   tipc: Add socket ...
2377
2378
  		value = skb_queue_len(&sk->sk_receive_queue);
  		break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2379
2380
2381
  	default:
  		res = -EINVAL;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2382
  	release_sock(sk);
25860c3bd   Paul Gortmaker   tipc: recode gets...
2383
2384
  	if (res)
  		return res;	/* "get" failed */
b97bf3fd8   Per Liden   [TIPC] Initial merge
2385

25860c3bd   Paul Gortmaker   tipc: recode gets...
2386
2387
2388
2389
2390
2391
2392
  	if (len < sizeof(value))
  		return -EINVAL;
  
  	if (copy_to_user(ov, &value, sizeof(value)))
  		return -EFAULT;
  
  	return put_user(sizeof(value), ol);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2393
  }
f2f9800d4   Ying Xue   tipc: make tipc n...
2394
  static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2395
  {
f2f9800d4   Ying Xue   tipc: make tipc n...
2396
  	struct sock *sk = sock->sk;
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2397
2398
2399
2400
2401
2402
2403
  	struct tipc_sioc_ln_req lnr;
  	void __user *argp = (void __user *)arg;
  
  	switch (cmd) {
  	case SIOCGETLINKNAME:
  		if (copy_from_user(&lnr, argp, sizeof(lnr)))
  			return -EFAULT;
f2f9800d4   Ying Xue   tipc: make tipc n...
2404
2405
  		if (!tipc_node_get_linkname(sock_net(sk),
  					    lnr.bearer_id & 0xffff, lnr.peer,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2406
2407
2408
2409
2410
2411
  					    lnr.linkname, TIPC_MAX_LINK_NAME)) {
  			if (copy_to_user(argp, &lnr, sizeof(lnr)))
  				return -EFAULT;
  			return 0;
  		}
  		return -EADDRNOTAVAIL;
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2412
2413
2414
2415
  	default:
  		return -ENOIOCTLCMD;
  	}
  }
ae86b9e38   Ben Hutchings   net: Fix non-kern...
2416
  /* Protocol switches for the various types of TIPC sockets */
bca65eae3   Florian Westphal   [TIPC]: declare p...
2417
  static const struct proto_ops msg_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2418
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2419
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
2420
2421
2422
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
2423
  	.socketpair	= sock_no_socketpair,
245f3d342   Ying Xue   tipc: Simplify pr...
2424
  	.accept		= sock_no_accept,
247f0f3c3   Ying Xue   tipc: align tipc ...
2425
2426
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2427
  	.ioctl		= tipc_ioctl,
245f3d342   Ying Xue   tipc: Simplify pr...
2428
  	.listen		= sock_no_listen,
247f0f3c3   Ying Xue   tipc: align tipc ...
2429
2430
2431
2432
2433
  	.shutdown	= tipc_shutdown,
  	.setsockopt	= tipc_setsockopt,
  	.getsockopt	= tipc_getsockopt,
  	.sendmsg	= tipc_sendmsg,
  	.recvmsg	= tipc_recvmsg,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2434
2435
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
2436
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
2437
  static const struct proto_ops packet_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2438
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2439
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
2440
2441
2442
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
2443
  	.socketpair	= sock_no_socketpair,
247f0f3c3   Ying Xue   tipc: align tipc ...
2444
2445
2446
  	.accept		= tipc_accept,
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2447
  	.ioctl		= tipc_ioctl,
247f0f3c3   Ying Xue   tipc: align tipc ...
2448
2449
2450
2451
2452
2453
  	.listen		= tipc_listen,
  	.shutdown	= tipc_shutdown,
  	.setsockopt	= tipc_setsockopt,
  	.getsockopt	= tipc_getsockopt,
  	.sendmsg	= tipc_send_packet,
  	.recvmsg	= tipc_recvmsg,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2454
2455
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
2456
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
2457
  static const struct proto_ops stream_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2458
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2459
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
2460
2461
2462
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
2463
  	.socketpair	= sock_no_socketpair,
247f0f3c3   Ying Xue   tipc: align tipc ...
2464
2465
2466
  	.accept		= tipc_accept,
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2467
  	.ioctl		= tipc_ioctl,
247f0f3c3   Ying Xue   tipc: align tipc ...
2468
2469
2470
2471
2472
2473
  	.listen		= tipc_listen,
  	.shutdown	= tipc_shutdown,
  	.setsockopt	= tipc_setsockopt,
  	.getsockopt	= tipc_getsockopt,
  	.sendmsg	= tipc_send_stream,
  	.recvmsg	= tipc_recv_stream,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2474
2475
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
2476
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
2477
  static const struct net_proto_family tipc_family_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2478
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2479
  	.family		= AF_TIPC,
c5fa7b3cf   Ying Xue   tipc: introduce n...
2480
  	.create		= tipc_sk_create
b97bf3fd8   Per Liden   [TIPC] Initial merge
2481
2482
2483
2484
2485
  };
  
  static struct proto tipc_proto = {
  	.name		= "TIPC",
  	.owner		= THIS_MODULE,
cc79dd1ba   Ying Xue   tipc: change sock...
2486
2487
  	.obj_size	= sizeof(struct tipc_sock),
  	.sysctl_rmem	= sysctl_tipc_rmem
b97bf3fd8   Per Liden   [TIPC] Initial merge
2488
2489
2490
  };
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
2491
   * tipc_socket_init - initialize TIPC socket interface
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2492
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
2493
2494
   * Returns 0 on success, errno otherwise
   */
4323add67   Per Liden   [TIPC] Avoid poll...
2495
  int tipc_socket_init(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2496
2497
  {
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2498
  	res = proto_register(&tipc_proto, 1);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2499
  	if (res) {
2cf8aa19f   Erik Hugne   tipc: use standar...
2500
2501
  		pr_err("Failed to register TIPC protocol type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
2502
2503
2504
2505
2506
  		goto out;
  	}
  
  	res = sock_register(&tipc_family_ops);
  	if (res) {
2cf8aa19f   Erik Hugne   tipc: use standar...
2507
2508
  		pr_err("Failed to register TIPC socket type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
2509
2510
2511
  		proto_unregister(&tipc_proto);
  		goto out;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
2512
2513
2514
2515
2516
   out:
  	return res;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
2517
   * tipc_socket_stop - stop TIPC socket interface
b97bf3fd8   Per Liden   [TIPC] Initial merge
2518
   */
4323add67   Per Liden   [TIPC] Avoid poll...
2519
  void tipc_socket_stop(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2520
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
2521
2522
2523
  	sock_unregister(tipc_family_ops.family);
  	proto_unregister(&tipc_proto);
  }
34b78a127   Richard Alpe   tipc: add sock du...
2524
2525
  
  /* Caller should hold socket lock for the passed tipc socket. */
d8182804c   Richard Alpe   tipc: fix sparse ...
2526
  static int __tipc_nl_add_sk_con(struct sk_buff *skb, struct tipc_sock *tsk)
34b78a127   Richard Alpe   tipc: add sock du...
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
  {
  	u32 peer_node;
  	u32 peer_port;
  	struct nlattr *nest;
  
  	peer_node = tsk_peer_node(tsk);
  	peer_port = tsk_peer_port(tsk);
  
  	nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON);
  
  	if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node))
  		goto msg_full;
  	if (nla_put_u32(skb, TIPC_NLA_CON_SOCK, peer_port))
  		goto msg_full;
  
  	if (tsk->conn_type != 0) {
  		if (nla_put_flag(skb, TIPC_NLA_CON_FLAG))
  			goto msg_full;
  		if (nla_put_u32(skb, TIPC_NLA_CON_TYPE, tsk->conn_type))
  			goto msg_full;
  		if (nla_put_u32(skb, TIPC_NLA_CON_INST, tsk->conn_instance))
  			goto msg_full;
  	}
  	nla_nest_end(skb, nest);
  
  	return 0;
  
  msg_full:
  	nla_nest_cancel(skb, nest);
  
  	return -EMSGSIZE;
  }
  
  /* Caller should hold socket lock for the passed tipc socket. */
d8182804c   Richard Alpe   tipc: fix sparse ...
2561
2562
  static int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb,
  			    struct tipc_sock *tsk)
34b78a127   Richard Alpe   tipc: add sock du...
2563
2564
2565
2566
  {
  	int err;
  	void *hdr;
  	struct nlattr *attrs;
347475395   Ying Xue   tipc: make tipc n...
2567
2568
  	struct net *net = sock_net(skb->sk);
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
34b78a127   Richard Alpe   tipc: add sock du...
2569
2570
  
  	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
bfb3e5dd8   Richard Alpe   tipc: move and re...
2571
  			  &tipc_genl_family, NLM_F_MULTI, TIPC_NL_SOCK_GET);
34b78a127   Richard Alpe   tipc: add sock du...
2572
2573
2574
2575
2576
2577
  	if (!hdr)
  		goto msg_cancel;
  
  	attrs = nla_nest_start(skb, TIPC_NLA_SOCK);
  	if (!attrs)
  		goto genlmsg_cancel;
07f6c4bc0   Ying Xue   tipc: convert tip...
2578
  	if (nla_put_u32(skb, TIPC_NLA_SOCK_REF, tsk->portid))
34b78a127   Richard Alpe   tipc: add sock du...
2579
  		goto attr_msg_cancel;
347475395   Ying Xue   tipc: make tipc n...
2580
  	if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tn->own_addr))
34b78a127   Richard Alpe   tipc: add sock du...
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
  		goto attr_msg_cancel;
  
  	if (tsk->connected) {
  		err = __tipc_nl_add_sk_con(skb, tsk);
  		if (err)
  			goto attr_msg_cancel;
  	} else if (!list_empty(&tsk->publications)) {
  		if (nla_put_flag(skb, TIPC_NLA_SOCK_HAS_PUBL))
  			goto attr_msg_cancel;
  	}
  	nla_nest_end(skb, attrs);
  	genlmsg_end(skb, hdr);
  
  	return 0;
  
  attr_msg_cancel:
  	nla_nest_cancel(skb, attrs);
  genlmsg_cancel:
  	genlmsg_cancel(skb, hdr);
  msg_cancel:
  	return -EMSGSIZE;
  }
  
  int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	int err;
  	struct tipc_sock *tsk;
07f6c4bc0   Ying Xue   tipc: convert tip...
2608
2609
  	const struct bucket_table *tbl;
  	struct rhash_head *pos;
e05b31f4b   Ying Xue   tipc: make tipc s...
2610
2611
  	struct net *net = sock_net(skb->sk);
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
d6e164e32   Richard Alpe   tipc: fix socket ...
2612
2613
  	u32 tbl_id = cb->args[0];
  	u32 prev_portid = cb->args[1];
34b78a127   Richard Alpe   tipc: add sock du...
2614

07f6c4bc0   Ying Xue   tipc: convert tip...
2615
  	rcu_read_lock();
e05b31f4b   Ying Xue   tipc: make tipc s...
2616
  	tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht);
d6e164e32   Richard Alpe   tipc: fix socket ...
2617
2618
  	for (; tbl_id < tbl->size; tbl_id++) {
  		rht_for_each_entry_rcu(tsk, pos, tbl, tbl_id, node) {
07f6c4bc0   Ying Xue   tipc: convert tip...
2619
  			spin_lock_bh(&tsk->sk.sk_lock.slock);
d6e164e32   Richard Alpe   tipc: fix socket ...
2620
2621
2622
2623
  			if (prev_portid && prev_portid != tsk->portid) {
  				spin_unlock_bh(&tsk->sk.sk_lock.slock);
  				continue;
  			}
07f6c4bc0   Ying Xue   tipc: convert tip...
2624
  			err = __tipc_nl_add_sk(skb, cb, tsk);
d6e164e32   Richard Alpe   tipc: fix socket ...
2625
2626
2627
2628
2629
2630
  			if (err) {
  				prev_portid = tsk->portid;
  				spin_unlock_bh(&tsk->sk.sk_lock.slock);
  				goto out;
  			}
  			prev_portid = 0;
07f6c4bc0   Ying Xue   tipc: convert tip...
2631
  			spin_unlock_bh(&tsk->sk.sk_lock.slock);
07f6c4bc0   Ying Xue   tipc: convert tip...
2632
  		}
34b78a127   Richard Alpe   tipc: add sock du...
2633
  	}
d6e164e32   Richard Alpe   tipc: fix socket ...
2634
  out:
07f6c4bc0   Ying Xue   tipc: convert tip...
2635
  	rcu_read_unlock();
d6e164e32   Richard Alpe   tipc: fix socket ...
2636
2637
  	cb->args[0] = tbl_id;
  	cb->args[1] = prev_portid;
34b78a127   Richard Alpe   tipc: add sock du...
2638
2639
2640
  
  	return skb->len;
  }
1a1a143da   Richard Alpe   tipc: add publica...
2641
2642
  
  /* Caller should hold socket lock for the passed tipc socket. */
d8182804c   Richard Alpe   tipc: fix sparse ...
2643
2644
2645
  static int __tipc_nl_add_sk_publ(struct sk_buff *skb,
  				 struct netlink_callback *cb,
  				 struct publication *publ)
1a1a143da   Richard Alpe   tipc: add publica...
2646
2647
2648
2649
2650
  {
  	void *hdr;
  	struct nlattr *attrs;
  
  	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
bfb3e5dd8   Richard Alpe   tipc: move and re...
2651
  			  &tipc_genl_family, NLM_F_MULTI, TIPC_NL_PUBL_GET);
1a1a143da   Richard Alpe   tipc: add publica...
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
  	if (!hdr)
  		goto msg_cancel;
  
  	attrs = nla_nest_start(skb, TIPC_NLA_PUBL);
  	if (!attrs)
  		goto genlmsg_cancel;
  
  	if (nla_put_u32(skb, TIPC_NLA_PUBL_KEY, publ->key))
  		goto attr_msg_cancel;
  	if (nla_put_u32(skb, TIPC_NLA_PUBL_TYPE, publ->type))
  		goto attr_msg_cancel;
  	if (nla_put_u32(skb, TIPC_NLA_PUBL_LOWER, publ->lower))
  		goto attr_msg_cancel;
  	if (nla_put_u32(skb, TIPC_NLA_PUBL_UPPER, publ->upper))
  		goto attr_msg_cancel;
  
  	nla_nest_end(skb, attrs);
  	genlmsg_end(skb, hdr);
  
  	return 0;
  
  attr_msg_cancel:
  	nla_nest_cancel(skb, attrs);
  genlmsg_cancel:
  	genlmsg_cancel(skb, hdr);
  msg_cancel:
  	return -EMSGSIZE;
  }
  
  /* Caller should hold socket lock for the passed tipc socket. */
d8182804c   Richard Alpe   tipc: fix sparse ...
2682
2683
2684
  static int __tipc_nl_list_sk_publ(struct sk_buff *skb,
  				  struct netlink_callback *cb,
  				  struct tipc_sock *tsk, u32 *last_publ)
1a1a143da   Richard Alpe   tipc: add publica...
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
  {
  	int err;
  	struct publication *p;
  
  	if (*last_publ) {
  		list_for_each_entry(p, &tsk->publications, pport_list) {
  			if (p->key == *last_publ)
  				break;
  		}
  		if (p->key != *last_publ) {
  			/* We never set seq or call nl_dump_check_consistent()
  			 * this means that setting prev_seq here will cause the
  			 * consistence check to fail in the netlink callback
  			 * handler. Resulting in the last NLMSG_DONE message
  			 * having the NLM_F_DUMP_INTR flag set.
  			 */
  			cb->prev_seq = 1;
  			*last_publ = 0;
  			return -EPIPE;
  		}
  	} else {
  		p = list_first_entry(&tsk->publications, struct publication,
  				     pport_list);
  	}
  
  	list_for_each_entry_from(p, &tsk->publications, pport_list) {
  		err = __tipc_nl_add_sk_publ(skb, cb, p);
  		if (err) {
  			*last_publ = p->key;
  			return err;
  		}
  	}
  	*last_publ = 0;
  
  	return 0;
  }
  
  int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	int err;
07f6c4bc0   Ying Xue   tipc: convert tip...
2725
  	u32 tsk_portid = cb->args[0];
1a1a143da   Richard Alpe   tipc: add publica...
2726
2727
  	u32 last_publ = cb->args[1];
  	u32 done = cb->args[2];
e05b31f4b   Ying Xue   tipc: make tipc s...
2728
  	struct net *net = sock_net(skb->sk);
1a1a143da   Richard Alpe   tipc: add publica...
2729
  	struct tipc_sock *tsk;
07f6c4bc0   Ying Xue   tipc: convert tip...
2730
  	if (!tsk_portid) {
1a1a143da   Richard Alpe   tipc: add publica...
2731
2732
2733
2734
2735
2736
  		struct nlattr **attrs;
  		struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1];
  
  		err = tipc_nlmsg_parse(cb->nlh, &attrs);
  		if (err)
  			return err;
45e093ae2   Richard Alpe   tipc: check nl so...
2737
2738
  		if (!attrs[TIPC_NLA_SOCK])
  			return -EINVAL;
1a1a143da   Richard Alpe   tipc: add publica...
2739
2740
2741
2742
2743
2744
2745
2746
  		err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX,
  				       attrs[TIPC_NLA_SOCK],
  				       tipc_nl_sock_policy);
  		if (err)
  			return err;
  
  		if (!sock[TIPC_NLA_SOCK_REF])
  			return -EINVAL;
07f6c4bc0   Ying Xue   tipc: convert tip...
2747
  		tsk_portid = nla_get_u32(sock[TIPC_NLA_SOCK_REF]);
1a1a143da   Richard Alpe   tipc: add publica...
2748
2749
2750
2751
  	}
  
  	if (done)
  		return 0;
e05b31f4b   Ying Xue   tipc: make tipc s...
2752
  	tsk = tipc_sk_lookup(net, tsk_portid);
1a1a143da   Richard Alpe   tipc: add publica...
2753
2754
2755
2756
2757
2758
2759
2760
  	if (!tsk)
  		return -EINVAL;
  
  	lock_sock(&tsk->sk);
  	err = __tipc_nl_list_sk_publ(skb, cb, tsk, &last_publ);
  	if (!err)
  		done = 1;
  	release_sock(&tsk->sk);
07f6c4bc0   Ying Xue   tipc: convert tip...
2761
  	sock_put(&tsk->sk);
1a1a143da   Richard Alpe   tipc: add publica...
2762

07f6c4bc0   Ying Xue   tipc: convert tip...
2763
  	cb->args[0] = tsk_portid;
1a1a143da   Richard Alpe   tipc: add publica...
2764
2765
2766
2767
2768
  	cb->args[1] = last_publ;
  	cb->args[2] = done;
  
  	return skb->len;
  }