Blame view

net/tipc/socket.c 73.5 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>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
37
  #include <linux/sched/signal.h>
b97bf3fd8   Per Liden   [TIPC] Initial merge
38
  #include "core.h"
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
39
  #include "name_table.h"
78acb1f9b   Erik Hugne   tipc: add ioctl t...
40
  #include "node.h"
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
41
  #include "link.h"
c637c1035   Jon Paul Maloy   tipc: resolve rac...
42
  #include "name_distr.h"
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
43
  #include "socket.h"
a6bf70f79   Jon Paul Maloy   tipc: simplify in...
44
  #include "bcast.h"
49cc66eae   Richard Alpe   tipc: move netlin...
45
  #include "netlink.h"
2cf8aa19f   Erik Hugne   tipc: use standar...
46

07f6c4bc0   Ying Xue   tipc: convert tip...
47
  #define CONN_TIMEOUT_DEFAULT	8000	/* default connect timeout = 8s */
2f55c4378   Ying Xue   tipc: remove unne...
48
  #define CONN_PROBING_INTERVAL	msecs_to_jiffies(3600000)  /* [ms] => 1 h */
07f6c4bc0   Ying Xue   tipc: convert tip...
49
  #define TIPC_FWD_MSG		1
07f6c4bc0   Ying Xue   tipc: convert tip...
50
51
  #define TIPC_MAX_PORT		0xffffffff
  #define TIPC_MIN_PORT		1
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
52
  #define TIPC_ACK_RATE		4       /* ACK at 1/4 of of rcv window size */
301bae56f   Jon Paul Maloy   tipc: merge struc...
53

0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
54
55
  enum {
  	TIPC_LISTEN = TCP_LISTEN,
8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
56
  	TIPC_ESTABLISHED = TCP_ESTABLISHED,
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
57
  	TIPC_OPEN = TCP_CLOSE,
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
58
  	TIPC_DISCONNECTING = TCP_CLOSE_WAIT,
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
59
  	TIPC_CONNECTING = TCP_SYN_SENT,
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
60
  };
301bae56f   Jon Paul Maloy   tipc: merge struc...
61
62
63
  /**
   * struct tipc_sock - TIPC socket structure
   * @sk: socket - interacts with 'port' and with user via the socket API
301bae56f   Jon Paul Maloy   tipc: merge struc...
64
65
66
67
   * @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...
68
   * @portid: unique port identity in TIPC socket hash table
301bae56f   Jon Paul Maloy   tipc: merge struc...
69
   * @phdr: preformatted message header used when sending messages
365ad353c   Jon Paul Maloy   tipc: reduce risk...
70
   * #cong_links: list of congested links
301bae56f   Jon Paul Maloy   tipc: merge struc...
71
   * @publications: list of publications for port
365ad353c   Jon Paul Maloy   tipc: reduce risk...
72
   * @blocking_link: address of the congested link we are currently sleeping on
301bae56f   Jon Paul Maloy   tipc: merge struc...
73
74
   * @pub_count: total # of publications port has made during its lifetime
   * @probing_state:
301bae56f   Jon Paul Maloy   tipc: merge struc...
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
365ad353c   Jon Paul Maloy   tipc: reduce risk...
77
   * @cong_link_cnt: number of congested links
301bae56f   Jon Paul Maloy   tipc: merge struc...
78
79
   * @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
aeda16b6a   Parthasarathy Bhuvaragan   tipc: rename tsk-...
80
   * @peer: 'connected' peer for dgram/rdm
07f6c4bc0   Ying Xue   tipc: convert tip...
81
   * @node: hash table node
01fd12bb1   Jon Paul Maloy   tipc: make replic...
82
   * @mc_method: cookie for use between socket and broadcast layer
07f6c4bc0   Ying Xue   tipc: convert tip...
83
   * @rcu: rcu struct for tipc_sock
301bae56f   Jon Paul Maloy   tipc: merge struc...
84
85
86
   */
  struct tipc_sock {
  	struct sock sk;
301bae56f   Jon Paul Maloy   tipc: merge struc...
87
88
89
90
  	u32 conn_type;
  	u32 conn_instance;
  	int published;
  	u32 max_pkt;
07f6c4bc0   Ying Xue   tipc: convert tip...
91
  	u32 portid;
301bae56f   Jon Paul Maloy   tipc: merge struc...
92
  	struct tipc_msg phdr;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
93
  	struct list_head cong_links;
301bae56f   Jon Paul Maloy   tipc: merge struc...
94
95
  	struct list_head publications;
  	u32 pub_count;
301bae56f   Jon Paul Maloy   tipc: merge struc...
96
97
  	uint conn_timeout;
  	atomic_t dupl_rcvcnt;
8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
98
  	bool probe_unacked;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
99
  	u16 cong_link_cnt;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
100
101
  	u16 snt_unacked;
  	u16 snd_win;
60020e185   Jon Paul Maloy   tipc: propagate p...
102
  	u16 peer_caps;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
103
104
  	u16 rcv_unacked;
  	u16 rcv_win;
aeda16b6a   Parthasarathy Bhuvaragan   tipc: rename tsk-...
105
  	struct sockaddr_tipc peer;
07f6c4bc0   Ying Xue   tipc: convert tip...
106
  	struct rhash_head node;
01fd12bb1   Jon Paul Maloy   tipc: make replic...
107
  	struct tipc_mc_method mc_method;
07f6c4bc0   Ying Xue   tipc: convert tip...
108
  	struct rcu_head rcu;
301bae56f   Jon Paul Maloy   tipc: merge struc...
109
  };
b97bf3fd8   Per Liden   [TIPC] Initial merge
110

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

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

301bae56f   Jon Paul Maloy   tipc: merge struc...
174
175
176
177
  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...
178
  static bool tsk_conn_cong(struct tipc_sock *tsk)
301bae56f   Jon Paul Maloy   tipc: merge struc...
179
  {
6998cc6ec   Jon Paul Maloy   tipc: resolve con...
180
  	return tsk->snt_unacked > tsk->snd_win;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  }
  
  /* 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...
201
  }
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
202
  /**
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
203
   * tsk_advance_rx_queue - discard first buffer in socket receive queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
204
205
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
206
   */
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
207
  static void tsk_advance_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
208
  {
5f6d9123f   Allan Stephens   tipc: Eliminate t...
209
  	kfree_skb(__skb_dequeue(&sk->sk_receive_queue));
b97bf3fd8   Per Liden   [TIPC] Initial merge
210
  }
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  /* 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 ...
226
  /**
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
227
   * tsk_rej_rx_queue - reject all buffers in socket receive queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
228
229
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
230
   */
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
231
  static void tsk_rej_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
232
  {
a6ca10944   Ying Xue   tipc: use generic...
233
  	struct sk_buff *skb;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
234

bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
235
236
  	while ((skb = __skb_dequeue(&sk->sk_receive_queue)))
  		tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
b97bf3fd8   Per Liden   [TIPC] Initial merge
237
  }
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
238
239
  static bool tipc_sk_connected(struct sock *sk)
  {
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
240
  	return sk->sk_state == TIPC_ESTABLISHED;
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
241
  }
c752023aa   Parthasarathy Bhuvaragan   tipc: remove sock...
242
243
244
245
246
247
248
249
250
  /* tipc_sk_type_connectionless - check if the socket is datagram socket
   * @sk: socket
   *
   * Returns true if connection less, false otherwise
   */
  static bool tipc_sk_type_connectionless(struct sock *sk)
  {
  	return sk->sk_type == SOCK_RDM || sk->sk_type == SOCK_DGRAM;
  }
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
251
  /* tsk_peer_msg - verify if message was sent by connected port's peer
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
252
253
254
255
   *
   * 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...
256
  static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg)
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
257
  {
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
258
259
  	struct sock *sk = &tsk->sk;
  	struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id);
301bae56f   Jon Paul Maloy   tipc: merge struc...
260
  	u32 peer_port = tsk_peer_port(tsk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
261
262
  	u32 orig_node;
  	u32 peer_node;
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
263
  	if (unlikely(!tipc_sk_connected(sk)))
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
264
265
266
267
268
269
  		return false;
  
  	if (unlikely(msg_origport(msg) != peer_port))
  		return false;
  
  	orig_node = msg_orignode(msg);
301bae56f   Jon Paul Maloy   tipc: merge struc...
270
  	peer_node = tsk_peer_node(tsk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
271
272
273
  
  	if (likely(orig_node == peer_node))
  		return true;
347475395   Ying Xue   tipc: make tipc n...
274
  	if (!orig_node && (peer_node == tn->own_addr))
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
275
  		return true;
347475395   Ying Xue   tipc: make tipc n...
276
  	if (!peer_node && (orig_node == tn->own_addr))
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
277
278
279
280
  		return true;
  
  	return false;
  }
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
281
282
283
284
285
286
287
288
289
  /* tipc_set_sk_state - set the sk_state of the socket
   * @sk: socket
   *
   * Caller must hold socket lock
   *
   * Returns 0 on success, errno otherwise
   */
  static int tipc_set_sk_state(struct sock *sk, int state)
  {
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
290
  	int oldsk_state = sk->sk_state;
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
291
292
293
  	int res = -EINVAL;
  
  	switch (state) {
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
294
295
296
  	case TIPC_OPEN:
  		res = 0;
  		break;
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
297
  	case TIPC_LISTEN:
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
298
  	case TIPC_CONNECTING:
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
299
  		if (oldsk_state == TIPC_OPEN)
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
300
301
  			res = 0;
  		break;
8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
302
  	case TIPC_ESTABLISHED:
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
303
  		if (oldsk_state == TIPC_CONNECTING ||
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
304
  		    oldsk_state == TIPC_OPEN)
8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
305
306
  			res = 0;
  		break;
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
307
  	case TIPC_DISCONNECTING:
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
308
  		if (oldsk_state == TIPC_CONNECTING ||
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
309
310
311
  		    oldsk_state == TIPC_ESTABLISHED)
  			res = 0;
  		break;
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
312
313
314
315
316
317
318
  	}
  
  	if (!res)
  		sk->sk_state = state;
  
  	return res;
  }
8c44e1af1   Jon Paul Maloy   tipc: unify tipc_...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
  static int tipc_sk_sock_err(struct socket *sock, long *timeout)
  {
  	struct sock *sk = sock->sk;
  	int err = sock_error(sk);
  	int typ = sock->type;
  
  	if (err)
  		return err;
  	if (typ == SOCK_STREAM || typ == SOCK_SEQPACKET) {
  		if (sk->sk_state == TIPC_DISCONNECTING)
  			return -EPIPE;
  		else if (!tipc_sk_connected(sk))
  			return -ENOTCONN;
  	}
  	if (!*timeout)
  		return -EAGAIN;
  	if (signal_pending(current))
  		return sock_intr_errno(*timeout);
  
  	return 0;
  }
844cf763f   Jon Paul Maloy   tipc: make macro ...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  #define tipc_wait_for_cond(sock_, timeo_, condition_)			       \
  ({                                                                             \
  	struct sock *sk_;						       \
  	int rc_;							       \
  									       \
  	while ((rc_ = !(condition_))) {					       \
  		DEFINE_WAIT_FUNC(wait_, woken_wake_function);	               \
  		sk_ = (sock_)->sk;					       \
  		rc_ = tipc_sk_sock_err((sock_), timeo_);		       \
  		if (rc_)						       \
  			break;						       \
  		prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE);    \
  		release_sock(sk_);					       \
  		*(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
  		sched_annotate_sleep();				               \
  		lock_sock(sk_);						       \
  		remove_wait_queue(sk_sleep(sk_), &wait_);		       \
  	}								       \
  	rc_;								       \
8c44e1af1   Jon Paul Maloy   tipc: unify tipc_...
359
  })
b97bf3fd8   Per Liden   [TIPC] Initial merge
360
  /**
c5fa7b3cf   Ying Xue   tipc: introduce n...
361
   * tipc_sk_create - create a TIPC socket
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
362
   * @net: network namespace (must be default network)
b97bf3fd8   Per Liden   [TIPC] Initial merge
363
364
   * @sock: pre-allocated socket structure
   * @protocol: protocol indicator (must be 0)
3f378b684   Eric Paris   net: pass kern to...
365
   * @kern: caused by kernel or by userspace?
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
366
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
367
368
   * This routine creates additional data structures used by the TIPC socket,
   * initializes them, and links them together.
b97bf3fd8   Per Liden   [TIPC] Initial merge
369
370
371
   *
   * Returns 0 on success, errno otherwise
   */
58ed94424   Jon Paul Maloy   tipc: align usage...
372
373
  static int tipc_sk_create(struct net *net, struct socket *sock,
  			  int protocol, int kern)
b97bf3fd8   Per Liden   [TIPC] Initial merge
374
  {
c5898636c   Jon Paul Maloy   tipc: reduce usag...
375
  	struct tipc_net *tn;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
376
  	const struct proto_ops *ops;
b97bf3fd8   Per Liden   [TIPC] Initial merge
377
  	struct sock *sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
378
  	struct tipc_sock *tsk;
5b8fa7ce8   Jon Paul Maloy   tipc: eliminate f...
379
  	struct tipc_msg *msg;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
380
381
  
  	/* Validate arguments */
b97bf3fd8   Per Liden   [TIPC] Initial merge
382
383
  	if (unlikely(protocol != 0))
  		return -EPROTONOSUPPORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
384
385
  	switch (sock->type) {
  	case SOCK_STREAM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
386
  		ops = &stream_ops;
b97bf3fd8   Per Liden   [TIPC] Initial merge
387
388
  		break;
  	case SOCK_SEQPACKET:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
389
  		ops = &packet_ops;
b97bf3fd8   Per Liden   [TIPC] Initial merge
390
391
  		break;
  	case SOCK_DGRAM:
b97bf3fd8   Per Liden   [TIPC] Initial merge
392
  	case SOCK_RDM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
393
  		ops = &msg_ops;
b97bf3fd8   Per Liden   [TIPC] Initial merge
394
  		break;
499786516   Allan Stephens   [TIPC]: Improved ...
395
  	default:
499786516   Allan Stephens   [TIPC]: Improved ...
396
  		return -EPROTOTYPE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
397
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
398
  	/* Allocate socket's protocol area */
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
399
  	sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, kern);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
400
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
401
  		return -ENOMEM;
b97bf3fd8   Per Liden   [TIPC] Initial merge
402

58ed94424   Jon Paul Maloy   tipc: align usage...
403
  	tsk = tipc_sk(sk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
404
  	tsk->max_pkt = MAX_PKT_DEFAULT;
301bae56f   Jon Paul Maloy   tipc: merge struc...
405
  	INIT_LIST_HEAD(&tsk->publications);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
406
  	INIT_LIST_HEAD(&tsk->cong_links);
301bae56f   Jon Paul Maloy   tipc: merge struc...
407
  	msg = &tsk->phdr;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
408
  	tn = net_generic(sock_net(sk), tipc_net_id);
b97bf3fd8   Per Liden   [TIPC] Initial merge
409

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
410
  	/* Finish initializing socket data structures */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
411
  	sock->ops = ops;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
412
  	sock_init_data(sock, sk);
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
413
  	tipc_set_sk_state(sk, TIPC_OPEN);
07f6c4bc0   Ying Xue   tipc: convert tip...
414
  	if (tipc_sk_insert(tsk)) {
c19ca6cb4   Masanari Iida   treewide: Fix typ...
415
416
  		pr_warn("Socket create failed; port number exhausted
  ");
07f6c4bc0   Ying Xue   tipc: convert tip...
417
418
  		return -EINVAL;
  	}
40f9f4397   Herbert Xu   tipc: Fix tipc_sk...
419
420
421
422
423
424
  
  	/* Ensure tsk is visible before we read own_addr. */
  	smp_mb();
  
  	tipc_msg_init(tn->own_addr, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG,
  		      NAMED_H_SIZE, 0);
07f6c4bc0   Ying Xue   tipc: convert tip...
425
  	msg_set_origport(msg, tsk->portid);
3721e9c7c   Ying Xue   tipc: remove redu...
426
  	setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk);
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
427
  	sk->sk_shutdown = 0;
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
428
  	sk->sk_backlog_rcv = tipc_backlog_rcv;
cc79dd1ba   Ying Xue   tipc: change sock...
429
  	sk->sk_rcvbuf = sysctl_tipc_rmem[1];
f288bef46   Ying Xue   tipc: fix race/in...
430
431
  	sk->sk_data_ready = tipc_data_ready;
  	sk->sk_write_space = tipc_write_space;
f4195d1ea   Ying Xue   tipc: avoid packe...
432
  	sk->sk_destruct = tipc_sock_destruct;
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
433
434
  	tsk->conn_timeout = CONN_TIMEOUT_DEFAULT;
  	atomic_set(&tsk->dupl_rcvcnt, 0);
7ef43ebaa   Allan Stephens   tipc: Fix race co...
435

10724cc7b   Jon Paul Maloy   tipc: redesign co...
436
437
438
  	/* 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;
c752023aa   Parthasarathy Bhuvaragan   tipc: remove sock...
439
  	if (tipc_sk_type_connectionless(sk)) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
440
  		tsk_set_unreturnable(tsk, true);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
441
  		if (sock->type == SOCK_DGRAM)
301bae56f   Jon Paul Maloy   tipc: merge struc...
442
  			tsk_set_unreliable(tsk, true);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
443
  	}
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
444

b97bf3fd8   Per Liden   [TIPC] Initial merge
445
446
  	return 0;
  }
07f6c4bc0   Ying Xue   tipc: convert tip...
447
448
449
450
451
452
  static void tipc_sk_callback(struct rcu_head *head)
  {
  	struct tipc_sock *tsk = container_of(head, struct tipc_sock, rcu);
  
  	sock_put(&tsk->sk);
  }
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
453
454
455
456
457
458
  /* Caller should hold socket lock for the socket. */
  static void __tipc_shutdown(struct socket *sock, int error)
  {
  	struct sock *sk = sock->sk;
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct net *net = sock_net(sk);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
459
  	long timeout = CONN_TIMEOUT_DEFAULT;
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
460
461
  	u32 dnode = tsk_peer_node(tsk);
  	struct sk_buff *skb;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
462
463
464
  	/* Avoid that hi-prio shutdown msgs bypass msgs in link wakeup queue */
  	tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt &&
  					    !tsk_conn_cong(tsk)));
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
465
466
467
468
469
470
  	/* Reject all unreceived messages, except on an active connection
  	 * (which disconnects locally & sends a 'FIN+' to peer).
  	 */
  	while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
  		if (TIPC_SKB_CB(skb)->bytes_read) {
  			kfree_skb(skb);
693c56491   Jon Paul Maloy   tipc: don't send ...
471
  			continue;
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
472
  		}
693c56491   Jon Paul Maloy   tipc: don't send ...
473
474
475
476
477
478
  		if (!tipc_sk_type_connectionless(sk) &&
  		    sk->sk_state != TIPC_DISCONNECTING) {
  			tipc_set_sk_state(sk, TIPC_DISCONNECTING);
  			tipc_node_remove_conn(net, dnode, tsk->portid);
  		}
  		tipc_sk_respond(sk, skb, error);
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
479
  	}
693c56491   Jon Paul Maloy   tipc: don't send ...
480
481
482
  
  	if (tipc_sk_type_connectionless(sk))
  		return;
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
483
484
485
486
487
488
489
  	if (sk->sk_state != TIPC_DISCONNECTING) {
  		skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
  				      TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
  				      tsk_own_node(tsk), tsk_peer_port(tsk),
  				      tsk->portid, error);
  		if (skb)
  			tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
693c56491   Jon Paul Maloy   tipc: don't send ...
490
491
  		tipc_node_remove_conn(net, dnode, tsk->portid);
  		tipc_set_sk_state(sk, TIPC_DISCONNECTING);
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
492
493
  	}
  }
c5fa7b3cf   Ying Xue   tipc: introduce n...
494
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
495
   * tipc_release - destroy a TIPC socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
496
497
498
499
500
501
502
   * @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...
503
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
504
505
506
507
508
509
   * 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 ...
510
  static int tipc_release(struct socket *sock)
b97bf3fd8   Per Liden   [TIPC] Initial merge
511
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
512
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
513
  	struct tipc_sock *tsk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
514

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
515
516
517
518
  	/*
  	 * 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 ...
519
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
520
  		return 0;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
521

58ed94424   Jon Paul Maloy   tipc: align usage...
522
  	tsk = tipc_sk(sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
523
  	lock_sock(sk);
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
524
525
  	__tipc_shutdown(sock, TIPC_ERR_NO_PORT);
  	sk->sk_shutdown = SHUTDOWN_MASK;
301bae56f   Jon Paul Maloy   tipc: merge struc...
526
  	tipc_sk_withdraw(tsk, 0, NULL);
1ea23a211   Ying Xue   tipc: uncondition...
527
  	sk_stop_timer(sk, &sk->sk_timer);
07f6c4bc0   Ying Xue   tipc: convert tip...
528
  	tipc_sk_remove(tsk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
529

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
530
  	/* Reject any messages that accumulated in backlog queue */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
531
  	release_sock(sk);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
532
533
  	u32_list_purge(&tsk->cong_links);
  	tsk->cong_link_cnt = 0;
07f6c4bc0   Ying Xue   tipc: convert tip...
534
  	call_rcu(&tsk->rcu, tipc_sk_callback);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
535
  	sock->sk = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
536

065d7e395   Geert Uytterhoeven   tipc: Let tipc_re...
537
  	return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
538
539
540
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
541
   * tipc_bind - associate or disassocate TIPC name(s) with a socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
542
543
544
   * @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...
545
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
546
547
548
   * 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...
549
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
550
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
551
552
553
   *
   * 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
554
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
555
556
  static int tipc_bind(struct socket *sock, struct sockaddr *uaddr,
  		     int uaddr_len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
557
  {
84602761c   Ying Xue   tipc: fix deadloc...
558
  	struct sock *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
559
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
58ed94424   Jon Paul Maloy   tipc: align usage...
560
  	struct tipc_sock *tsk = tipc_sk(sk);
84602761c   Ying Xue   tipc: fix deadloc...
561
  	int res = -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
562

84602761c   Ying Xue   tipc: fix deadloc...
563
564
  	lock_sock(sk);
  	if (unlikely(!uaddr_len)) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
565
  		res = tipc_sk_withdraw(tsk, 0, NULL);
84602761c   Ying Xue   tipc: fix deadloc...
566
567
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
568

84602761c   Ying Xue   tipc: fix deadloc...
569
570
571
572
573
574
575
576
  	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
577

b97bf3fd8   Per Liden   [TIPC] Initial merge
578
579
  	if (addr->addrtype == TIPC_ADDR_NAME)
  		addr->addr.nameseq.upper = addr->addr.nameseq.lower;
84602761c   Ying Xue   tipc: fix deadloc...
580
581
582
583
  	else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
  		res = -EAFNOSUPPORT;
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
584

13a2e8987   Ying Xue   tipc: convert top...
585
  	if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
7d0ab17b7   Ying Xue   tipc: convert con...
586
  	    (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
84602761c   Ying Xue   tipc: fix deadloc...
587
588
589
590
  	    (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
  		res = -EACCES;
  		goto exit;
  	}
c422f1bdc   Allan Stephens   tipc: Simplify en...
591

84602761c   Ying Xue   tipc: fix deadloc...
592
  	res = (addr->scope > 0) ?
301bae56f   Jon Paul Maloy   tipc: merge struc...
593
594
  		tipc_sk_publish(tsk, addr->scope, &addr->addr.nameseq) :
  		tipc_sk_withdraw(tsk, -addr->scope, &addr->addr.nameseq);
84602761c   Ying Xue   tipc: fix deadloc...
595
596
597
  exit:
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
598
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
599
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
600
   * tipc_getname - get port ID of socket or peer socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
601
602
603
   * @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...
604
   * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
605
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
606
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
607
   *
2da59918e   Allan Stephens   tipc: Fix race co...
608
609
   * 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...
610
   *       a completely predictable manner).
b97bf3fd8   Per Liden   [TIPC] Initial merge
611
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
612
613
  static int tipc_getname(struct socket *sock, struct sockaddr *uaddr,
  			int *uaddr_len, int peer)
b97bf3fd8   Per Liden   [TIPC] Initial merge
614
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
615
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
616
617
  	struct sock *sk = sock->sk;
  	struct tipc_sock *tsk = tipc_sk(sk);
347475395   Ying Xue   tipc: make tipc n...
618
  	struct tipc_net *tn = net_generic(sock_net(sock->sk), tipc_net_id);
b97bf3fd8   Per Liden   [TIPC] Initial merge
619

88f8a5e3e   Kulikov Vasiliy   net: tipc: fix in...
620
  	memset(addr, 0, sizeof(*addr));
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
621
  	if (peer) {
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
622
  		if ((!tipc_sk_connected(sk)) &&
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
623
  		    ((peer != 2) || (sk->sk_state != TIPC_DISCONNECTING)))
2da59918e   Allan Stephens   tipc: Fix race co...
624
  			return -ENOTCONN;
301bae56f   Jon Paul Maloy   tipc: merge struc...
625
626
  		addr->addr.id.ref = tsk_peer_port(tsk);
  		addr->addr.id.node = tsk_peer_node(tsk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
627
  	} else {
07f6c4bc0   Ying Xue   tipc: convert tip...
628
  		addr->addr.id.ref = tsk->portid;
347475395   Ying Xue   tipc: make tipc n...
629
  		addr->addr.id.node = tn->own_addr;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
630
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
631
632
633
634
635
  
  	*uaddr_len = sizeof(*addr);
  	addr->addrtype = TIPC_ADDR_ID;
  	addr->family = AF_TIPC;
  	addr->scope = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
636
  	addr->addr.name.domain = 0;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
637
  	return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
638
639
640
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
641
   * tipc_poll - read and possibly block on pollmask
b97bf3fd8   Per Liden   [TIPC] Initial merge
642
643
644
645
   * @file: file structure associated with the socket
   * @sock: socket for which to calculate the poll bits
   * @wait: ???
   *
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
646
647
648
649
650
651
652
653
   * 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 ...
   *
f662c0705   Allan Stephens   tipc: correct pro...
654
655
656
   * 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
657
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
658
659
  static unsigned int tipc_poll(struct file *file, struct socket *sock,
  			      poll_table *wait)
b97bf3fd8   Per Liden   [TIPC] Initial merge
660
  {
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
661
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
662
  	struct tipc_sock *tsk = tipc_sk(sk);
f662c0705   Allan Stephens   tipc: correct pro...
663
  	u32 mask = 0;
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
664

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

6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
667
668
669
670
  	if (sk->sk_shutdown & RCV_SHUTDOWN)
  		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
  	if (sk->sk_shutdown == SHUTDOWN_MASK)
  		mask |= POLLHUP;
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
671
672
  	switch (sk->sk_state) {
  	case TIPC_ESTABLISHED:
92ae82334   Parthasarathy Bhuvaragan   tipc: fix hanging...
673
  	case TIPC_CONNECTING:
365ad353c   Jon Paul Maloy   tipc: reduce risk...
674
  		if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk))
f662c0705   Allan Stephens   tipc: correct pro...
675
  			mask |= POLLOUT;
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
676
677
  		/* fall thru' */
  	case TIPC_LISTEN:
f662c0705   Allan Stephens   tipc: correct pro...
678
679
  		if (!skb_queue_empty(&sk->sk_receive_queue))
  			mask |= (POLLIN | POLLRDNORM);
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
680
681
  		break;
  	case TIPC_OPEN:
365ad353c   Jon Paul Maloy   tipc: reduce risk...
682
  		if (!tsk->cong_link_cnt)
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
683
684
685
686
687
688
689
690
  			mask |= POLLOUT;
  		if (tipc_sk_type_connectionless(sk) &&
  		    (!skb_queue_empty(&sk->sk_receive_queue)))
  			mask |= (POLLIN | POLLRDNORM);
  		break;
  	case TIPC_DISCONNECTING:
  		mask = (POLLIN | POLLRDNORM | POLLHUP);
  		break;
f662c0705   Allan Stephens   tipc: correct pro...
691
  	}
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
692
693
  
  	return mask;
b97bf3fd8   Per Liden   [TIPC] Initial merge
694
  }
0abd8ff21   Jon Paul Maloy   tipc: start using...
695
696
697
698
  /**
   * tipc_sendmcast - send multicast message
   * @sock: socket structure
   * @seq: destination address
562640f3c   Al Viro   tipc_sendmsg(): p...
699
   * @msg: message to send
365ad353c   Jon Paul Maloy   tipc: reduce risk...
700
701
   * @dlen: length of data to send
   * @timeout: timeout to wait for wakeup
0abd8ff21   Jon Paul Maloy   tipc: start using...
702
703
704
705
706
   *
   * 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,
365ad353c   Jon Paul Maloy   tipc: reduce risk...
707
  			  struct msghdr *msg, size_t dlen, long timeout)
0abd8ff21   Jon Paul Maloy   tipc: start using...
708
709
  {
  	struct sock *sk = sock->sk;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
710
  	struct tipc_sock *tsk = tipc_sk(sk);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
711
  	struct tipc_msg *hdr = &tsk->phdr;
f2f9800d4   Ying Xue   tipc: make tipc n...
712
  	struct net *net = sock_net(sk);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
713
  	int mtu = tipc_bcast_get_mtu(net);
01fd12bb1   Jon Paul Maloy   tipc: make replic...
714
  	struct tipc_mc_method *method = &tsk->mc_method;
a853e4c6d   Jon Paul Maloy   tipc: introduce r...
715
  	u32 domain = addr_domain(net, TIPC_CLUSTER_SCOPE);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
716
  	struct sk_buff_head pkts;
a853e4c6d   Jon Paul Maloy   tipc: introduce r...
717
  	struct tipc_nlist dsts;
0abd8ff21   Jon Paul Maloy   tipc: start using...
718
  	int rc;
a853e4c6d   Jon Paul Maloy   tipc: introduce r...
719
  	/* Block or return if any destination link is congested */
365ad353c   Jon Paul Maloy   tipc: reduce risk...
720
721
722
  	rc = tipc_wait_for_cond(sock, &timeout, !tsk->cong_link_cnt);
  	if (unlikely(rc))
  		return rc;
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
723

a853e4c6d   Jon Paul Maloy   tipc: introduce r...
724
725
726
727
728
729
730
731
  	/* Lookup destination nodes */
  	tipc_nlist_init(&dsts, tipc_own_addr(net));
  	tipc_nametbl_lookup_dst_nodes(net, seq->type, seq->lower,
  				      seq->upper, domain, &dsts);
  	if (!dsts.local && !dsts.remote)
  		return -EHOSTUNREACH;
  
  	/* Build message header */
365ad353c   Jon Paul Maloy   tipc: reduce risk...
732
  	msg_set_type(hdr, TIPC_MCAST_MSG);
a853e4c6d   Jon Paul Maloy   tipc: introduce r...
733
  	msg_set_hdr_sz(hdr, MCAST_H_SIZE);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
734
735
736
737
738
739
  	msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE);
  	msg_set_destport(hdr, 0);
  	msg_set_destnode(hdr, 0);
  	msg_set_nametype(hdr, seq->type);
  	msg_set_namelower(hdr, seq->lower);
  	msg_set_nameupper(hdr, seq->upper);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
740

a853e4c6d   Jon Paul Maloy   tipc: introduce r...
741
  	/* Build message as chain of buffers */
365ad353c   Jon Paul Maloy   tipc: reduce risk...
742
743
  	skb_queue_head_init(&pkts);
  	rc = tipc_msg_build(hdr, msg, 0, dlen, mtu, &pkts);
0abd8ff21   Jon Paul Maloy   tipc: start using...
744

a853e4c6d   Jon Paul Maloy   tipc: introduce r...
745
746
  	/* Send message if build was successful */
  	if (unlikely(rc == dlen))
01fd12bb1   Jon Paul Maloy   tipc: make replic...
747
  		rc = tipc_mcast_xmit(net, &pkts, method, &dsts,
a853e4c6d   Jon Paul Maloy   tipc: introduce r...
748
749
750
  				     &tsk->cong_link_cnt);
  
  	tipc_nlist_purge(&dsts);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
751
752
  
  	return rc ? rc : dlen;
0abd8ff21   Jon Paul Maloy   tipc: start using...
753
  }
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
754
755
756
757
758
759
  /**
   * 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...
760
   */
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
761
762
  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...
763
  {
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
764
  	struct tipc_msg *msg;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
765
  	struct list_head dports;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
766
  	u32 portid;
078bec826   Jon Paul Maloy   tipc: add new fun...
767
  	u32 scope = TIPC_CLUSTER_SCOPE;
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
768
769
770
  	struct sk_buff_head tmpq;
  	uint hsz;
  	struct sk_buff *skb, *_skb;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
771

cb1b72809   Jon Paul Maloy   tipc: eliminate r...
772
  	__skb_queue_head_init(&tmpq);
4d8642d89   Jon Paul Maloy   tipc: modify stru...
773
  	INIT_LIST_HEAD(&dports);
078bec826   Jon Paul Maloy   tipc: add new fun...
774

cb1b72809   Jon Paul Maloy   tipc: eliminate r...
775
776
777
778
779
780
781
782
783
784
785
786
  	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);
4d8642d89   Jon Paul Maloy   tipc: modify stru...
787
788
  		portid = u32_pop(&dports);
  		for (; portid; portid = u32_pop(&dports)) {
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
789
790
791
792
793
794
795
796
  			_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...
797
  		}
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
798
799
800
801
802
803
804
805
806
  		/* 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...
807
  	}
cb1b72809   Jon Paul Maloy   tipc: eliminate r...
808
  	tipc_sk_rcv(net, inputq);
078bec826   Jon Paul Maloy   tipc: add new fun...
809
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
810
  /**
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
811
812
   * tipc_sk_proto_rcv - receive a connection mng protocol message
   * @tsk: receiving socket
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
813
   * @skb: pointer to message buffer.
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
814
   */
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
815
816
  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...
817
  {
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
818
  	struct sock *sk = &tsk->sk;
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
819
  	u32 onode = tsk_own_node(tsk);
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
820
821
  	struct tipc_msg *hdr = buf_msg(skb);
  	int mtyp = msg_type(hdr);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
822
  	bool conn_cong;
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
823

ac0074ee7   Jon Paul Maloy   tipc: clean up co...
824
  	/* Ignore if connection cannot be validated: */
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
825
  	if (!tsk_peer_msg(tsk, hdr))
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
826
  		goto exit;
c1be77562   Parthasarathy Bhuvaragan   tipc: close the c...
827
828
829
830
831
832
833
  	if (unlikely(msg_errcode(hdr))) {
  		tipc_set_sk_state(sk, TIPC_DISCONNECTING);
  		tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk),
  				      tsk_peer_port(tsk));
  		sk->sk_state_change(sk);
  		goto exit;
  	}
8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
834
  	tsk->probe_unacked = false;
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
835

bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
836
837
  	if (mtyp == CONN_PROBE) {
  		msg_set_type(hdr, CONN_PROBE_REPLY);
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
838
839
  		if (tipc_msg_reverse(onode, &skb, TIPC_OK))
  			__skb_queue_tail(xmitq, skb);
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
840
841
  		return;
  	} else if (mtyp == CONN_ACK) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
842
  		conn_cong = tsk_conn_cong(tsk);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
843
844
845
  		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...
846
  		if (conn_cong)
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
847
848
849
850
  			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...
851
  	}
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
852
  exit:
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
853
  	kfree_skb(skb);
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
854
  }
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
855
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
856
   * tipc_sendmsg - send message in connectionless manner
b97bf3fd8   Per Liden   [TIPC] Initial merge
857
858
   * @sock: socket structure
   * @m: message to send
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
859
   * @dsz: amount of user data to be sent
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
860
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
861
   * Message must have an destination specified explicitly.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
862
   * Used for SOCK_RDM and SOCK_DGRAM messages,
b97bf3fd8   Per Liden   [TIPC] Initial merge
863
864
   * 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...
865
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
866
867
   * Returns the number of bytes sent on success, or errno otherwise
   */
1b7841404   Ying Xue   net: Remove iocb ...
868
  static int tipc_sendmsg(struct socket *sock,
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
869
  			struct msghdr *m, size_t dsz)
b97bf3fd8   Per Liden   [TIPC] Initial merge
870
  {
39a0295f9   Ying Xue   tipc: Don't use i...
871
872
873
874
875
876
877
878
879
  	struct sock *sk = sock->sk;
  	int ret;
  
  	lock_sock(sk);
  	ret = __tipc_sendmsg(sock, m, dsz);
  	release_sock(sk);
  
  	return ret;
  }
365ad353c   Jon Paul Maloy   tipc: reduce risk...
880
  static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
39a0295f9   Ying Xue   tipc: Don't use i...
881
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
882
  	struct sock *sk = sock->sk;
f2f9800d4   Ying Xue   tipc: make tipc n...
883
  	struct net *net = sock_net(sk);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
884
885
886
887
888
889
  	struct tipc_sock *tsk = tipc_sk(sk);
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
  	long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
  	struct list_head *clinks = &tsk->cong_links;
  	bool syn = !tipc_sk_type_connectionless(sk);
  	struct tipc_msg *hdr = &tsk->phdr;
f2f8036e3   Erik Hugne   tipc: add support...
890
  	struct tipc_name_seq *seq;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
891
892
893
894
  	struct sk_buff_head pkts;
  	u32 type, inst, domain;
  	u32 dnode, dport;
  	int mtu, rc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
895

365ad353c   Jon Paul Maloy   tipc: reduce risk...
896
  	if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE))
c29c3f70c   Allan Stephens   tipc: Abort exces...
897
  		return -EMSGSIZE;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
898

f2f8036e3   Erik Hugne   tipc: add support...
899
  	if (unlikely(!dest)) {
365ad353c   Jon Paul Maloy   tipc: reduce risk...
900
901
  		dest = &tsk->peer;
  		if (!syn || dest->family != AF_TIPC)
f2f8036e3   Erik Hugne   tipc: add support...
902
  			return -EDESTADDRREQ;
f2f8036e3   Erik Hugne   tipc: add support...
903
  	}
365ad353c   Jon Paul Maloy   tipc: reduce risk...
904
905
906
907
908
909
910
911
  
  	if (unlikely(m->msg_namelen < sizeof(*dest)))
  		return -EINVAL;
  
  	if (unlikely(dest->family != AF_TIPC))
  		return -EINVAL;
  
  	if (unlikely(syn)) {
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
912
  		if (sk->sk_state == TIPC_LISTEN)
39a0295f9   Ying Xue   tipc: Don't use i...
913
  			return -EPIPE;
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
914
  		if (sk->sk_state != TIPC_OPEN)
39a0295f9   Ying Xue   tipc: Don't use i...
915
916
917
  			return -EISCONN;
  		if (tsk->published)
  			return -EOPNOTSUPP;
3388007bc   Allan Stephens   [TIPC]: Implied c...
918
  		if (dest->addrtype == TIPC_ADDR_NAME) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
919
920
  			tsk->conn_type = dest->addr.name.name.type;
  			tsk->conn_instance = dest->addr.name.name.instance;
3388007bc   Allan Stephens   [TIPC]: Implied c...
921
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
922
  	}
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
923

365ad353c   Jon Paul Maloy   tipc: reduce risk...
924
925
926
  	seq = &dest->addr.nameseq;
  	if (dest->addrtype == TIPC_ADDR_MCAST)
  		return tipc_sendmcast(sock, seq, m, dlen, timeout);
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
927

365ad353c   Jon Paul Maloy   tipc: reduce risk...
928
929
930
931
  	if (dest->addrtype == TIPC_ADDR_NAME) {
  		type = dest->addr.name.name.type;
  		inst = dest->addr.name.name.instance;
  		domain = dest->addr.name.domain;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
932
  		dnode = domain;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
933
934
935
936
937
  		msg_set_type(hdr, TIPC_NAMED_MSG);
  		msg_set_hdr_sz(hdr, NAMED_H_SIZE);
  		msg_set_nametype(hdr, type);
  		msg_set_nameinst(hdr, inst);
  		msg_set_lookup_scope(hdr, tipc_addr_scope(domain));
4ac1c8d0e   Ying Xue   tipc: name tipc n...
938
  		dport = tipc_nametbl_translate(net, type, inst, &dnode);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
939
940
  		msg_set_destnode(hdr, dnode);
  		msg_set_destport(hdr, dport);
39a0295f9   Ying Xue   tipc: Don't use i...
941
942
  		if (unlikely(!dport && !dnode))
  			return -EHOSTUNREACH;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
943

e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
944
945
  	} else if (dest->addrtype == TIPC_ADDR_ID) {
  		dnode = dest->addr.id.node;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
946
947
948
949
950
  		msg_set_type(hdr, TIPC_DIRECT_MSG);
  		msg_set_lookup_scope(hdr, 0);
  		msg_set_destnode(hdr, dnode);
  		msg_set_destport(hdr, dest->addr.id.ref);
  		msg_set_hdr_sz(hdr, BASIC_H_SIZE);
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
951
  	}
365ad353c   Jon Paul Maloy   tipc: reduce risk...
952
953
954
955
956
957
  	/* Block or return if destination link is congested */
  	rc = tipc_wait_for_cond(sock, &timeout, !u32_find(clinks, dnode));
  	if (unlikely(rc))
  		return rc;
  
  	skb_queue_head_init(&pkts);
f2f9800d4   Ying Xue   tipc: make tipc n...
958
  	mtu = tipc_node_get_mtu(net, dnode, tsk->portid);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
959
960
  	rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts);
  	if (unlikely(rc != dlen))
39a0295f9   Ying Xue   tipc: Don't use i...
961
  		return rc;
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
962

365ad353c   Jon Paul Maloy   tipc: reduce risk...
963
964
965
966
967
968
  	rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid);
  	if (unlikely(rc == -ELINKCONG)) {
  		u32_push(clinks, dnode);
  		tsk->cong_link_cnt++;
  		rc = 0;
  	}
e2dafe87d   Jon Paul Maloy   tipc: RDM/DGRAM t...
969

365ad353c   Jon Paul Maloy   tipc: reduce risk...
970
971
972
973
  	if (unlikely(syn && !rc))
  		tipc_set_sk_state(sk, TIPC_CONNECTING);
  
  	return rc ? rc : dlen;
b97bf3fd8   Per Liden   [TIPC] Initial merge
974
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
975
  /**
365ad353c   Jon Paul Maloy   tipc: reduce risk...
976
   * tipc_sendstream - send stream-oriented data
b97bf3fd8   Per Liden   [TIPC] Initial merge
977
   * @sock: socket structure
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
978
979
   * @m: data to send
   * @dsz: total length of data to be transmitted
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
980
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
981
   * Used for SOCK_STREAM data.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
982
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
983
984
   * Returns the number of bytes sent on success (or partial success),
   * or errno if no data sent
b97bf3fd8   Per Liden   [TIPC] Initial merge
985
   */
365ad353c   Jon Paul Maloy   tipc: reduce risk...
986
  static int tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dsz)
b97bf3fd8   Per Liden   [TIPC] Initial merge
987
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
988
  	struct sock *sk = sock->sk;
39a0295f9   Ying Xue   tipc: Don't use i...
989
990
991
  	int ret;
  
  	lock_sock(sk);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
992
  	ret = __tipc_sendstream(sock, m, dsz);
39a0295f9   Ying Xue   tipc: Don't use i...
993
994
995
996
  	release_sock(sk);
  
  	return ret;
  }
365ad353c   Jon Paul Maloy   tipc: reduce risk...
997
  static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dlen)
39a0295f9   Ying Xue   tipc: Don't use i...
998
999
  {
  	struct sock *sk = sock->sk;
342dfc306   Steffen Hurrle   net: add build-ti...
1000
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1001
1002
1003
1004
1005
1006
1007
1008
  	long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_msg *hdr = &tsk->phdr;
  	struct net *net = sock_net(sk);
  	struct sk_buff_head pkts;
  	u32 dnode = tsk_peer_node(tsk);
  	int send, sent = 0;
  	int rc = 0;
1d835874a   Ying Xue   tipc: Add support...
1009

365ad353c   Jon Paul Maloy   tipc: reduce risk...
1010
  	skb_queue_head_init(&pkts);
7cf87fa27   Parthasarathy Bhuvaragan   tipc: return earl...
1011

365ad353c   Jon Paul Maloy   tipc: reduce risk...
1012
1013
  	if (unlikely(dlen > INT_MAX))
  		return -EMSGSIZE;
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1014

365ad353c   Jon Paul Maloy   tipc: reduce risk...
1015
1016
1017
  	/* Handle implicit connection setup */
  	if (unlikely(dest)) {
  		rc = __tipc_sendmsg(sock, m, dlen);
49984ca4e   Parthasarathy Bhuvaragan   tipc: fix flow co...
1018
1019
  		if (dlen && dlen == rc) {
  			tsk->peer_caps = tipc_node_get_capabilities(net, dnode);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1020
  			tsk->snt_unacked = tsk_inc(tsk, dlen + msg_hdr_sz(hdr));
49984ca4e   Parthasarathy Bhuvaragan   tipc: fix flow co...
1021
  		}
39a0295f9   Ying Xue   tipc: Don't use i...
1022
  		return rc;
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1023
  	}
f214fc402   Parthasarathy Bhuvaragan   tipc: Revert "tip...
1024

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1025
  	do {
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1026
1027
  		rc = tipc_wait_for_cond(sock, &timeout,
  					(!tsk->cong_link_cnt &&
8c44e1af1   Jon Paul Maloy   tipc: unify tipc_...
1028
1029
  					 !tsk_conn_cong(tsk) &&
  					 tipc_sk_connected(sk)));
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
  		if (unlikely(rc))
  			break;
  
  		send = min_t(size_t, dlen - sent, TIPC_MAX_USER_MSG_SIZE);
  		rc = tipc_msg_build(hdr, m, sent, send, tsk->max_pkt, &pkts);
  		if (unlikely(rc != send))
  			break;
  
  		rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid);
  		if (unlikely(rc == -ELINKCONG)) {
  			tsk->cong_link_cnt = 1;
  			rc = 0;
  		}
  		if (likely(!rc)) {
  			tsk->snt_unacked += tsk_inc(tsk, send + MIN_H_SIZE);
  			sent += send;
  		}
  	} while (sent < dlen && !rc);
39a0295f9   Ying Xue   tipc: Don't use i...
1048

3364d61c9   Parthasarathy Bhuvaragan   tipc: fix socket ...
1049
  	return sent ? sent : rc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1050
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1051
  /**
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1052
   * tipc_send_packet - send a connection-oriented message
b97bf3fd8   Per Liden   [TIPC] Initial merge
1053
   * @sock: socket structure
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1054
1055
   * @m: message to send
   * @dsz: length of data to be transmitted
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1056
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1057
   * Used for SOCK_SEQPACKET messages.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1058
   *
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1059
   * Returns the number of bytes sent on success, or errno otherwise
b97bf3fd8   Per Liden   [TIPC] Initial merge
1060
   */
1b7841404   Ying Xue   net: Remove iocb ...
1061
  static int tipc_send_packet(struct socket *sock, struct msghdr *m, size_t dsz)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1062
  {
4ccfe5e04   Jon Paul Maloy   tipc: connection ...
1063
1064
  	if (dsz > TIPC_MAX_USER_MSG_SIZE)
  		return -EMSGSIZE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1065

365ad353c   Jon Paul Maloy   tipc: reduce risk...
1066
  	return tipc_sendstream(sock, m, dsz);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1067
  }
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1068
  /* tipc_sk_finish_conn - complete the setup of a connection
b97bf3fd8   Per Liden   [TIPC] Initial merge
1069
   */
301bae56f   Jon Paul Maloy   tipc: merge struc...
1070
  static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port,
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1071
  				u32 peer_node)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1072
  {
3721e9c7c   Ying Xue   tipc: remove redu...
1073
1074
  	struct sock *sk = &tsk->sk;
  	struct net *net = sock_net(sk);
301bae56f   Jon Paul Maloy   tipc: merge struc...
1075
  	struct tipc_msg *msg = &tsk->phdr;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1076

dadebc002   Jon Paul Maloy   tipc: eliminate p...
1077
1078
1079
1080
1081
  	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...
1082

360aab6b4   Parthasarathy Bhuvaragan   tipc: remove prob...
1083
  	sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL);
8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
1084
  	tipc_set_sk_state(sk, TIPC_ESTABLISHED);
f2f9800d4   Ying Xue   tipc: make tipc n...
1085
1086
  	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...
1087
  	tsk->peer_caps = tipc_node_get_capabilities(net, peer_node);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1088
1089
1090
1091
1092
1093
  	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
1094
1095
1096
1097
1098
1099
  }
  
  /**
   * 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...
1100
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1101
1102
   * Note: Address is not captured if not requested by receiver.
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
1103
  static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1104
  {
342dfc306   Steffen Hurrle   net: add build-ti...
1105
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, addr, m->msg_name);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1106

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1107
  	if (addr) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
1108
1109
  		addr->family = AF_TIPC;
  		addr->addrtype = TIPC_ADDR_ID;
60085c3d0   Mathias Krause   tipc: fix info le...
1110
  		memset(&addr->addr, 0, sizeof(addr->addr));
b97bf3fd8   Per Liden   [TIPC] Initial merge
1111
1112
  		addr->addr.id.ref = msg_origport(msg);
  		addr->addr.id.node = msg_orignode(msg);
0e65967e3   Allan Stephens   tipc: cleanup var...
1113
1114
  		addr->addr.name.domain = 0;	/* could leave uninitialized */
  		addr->scope = 0;		/* could leave uninitialized */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1115
1116
1117
1118
1119
  		m->msg_namelen = sizeof(struct sockaddr_tipc);
  	}
  }
  
  /**
301bae56f   Jon Paul Maloy   tipc: merge struc...
1120
   * tipc_sk_anc_data_recv - optionally capture ancillary data for received message
b97bf3fd8   Per Liden   [TIPC] Initial merge
1121
1122
   * @m: descriptor for message info
   * @msg: received message header
301bae56f   Jon Paul Maloy   tipc: merge struc...
1123
   * @tsk: TIPC port associated with message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1124
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1125
   * Note: Ancillary data is not captured if not requested by receiver.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1126
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1127
1128
   * Returns 0 if successful, otherwise errno
   */
301bae56f   Jon Paul Maloy   tipc: merge struc...
1129
1130
  static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
  				 struct tipc_sock *tsk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1131
1132
1133
1134
  {
  	u32 anc_data[3];
  	u32 err;
  	u32 dest_type;
3546c7508   Allan Stephens   [TIPC]: Can now r...
1135
  	int has_name;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1136
1137
1138
1139
1140
1141
  	int res;
  
  	if (likely(m->msg_controllen == 0))
  		return 0;
  
  	/* Optionally capture errored message object(s) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1142
1143
1144
1145
  	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...
1146
1147
  		res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1148
  			return res;
2db9983a4   Allan Stephens   tipc: split varia...
1149
1150
1151
1152
1153
1154
  		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
1155
1156
1157
  	}
  
  	/* Optionally capture message destination object */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1158
1159
1160
  	dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
  	switch (dest_type) {
  	case TIPC_NAMED_MSG:
3546c7508   Allan Stephens   [TIPC]: Can now r...
1161
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1162
1163
1164
1165
1166
  		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...
1167
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1168
1169
1170
1171
1172
  		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...
1173
1174
1175
1176
  		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
1177
1178
  		break;
  	default:
3546c7508   Allan Stephens   [TIPC]: Can now r...
1179
  		has_name = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1180
  	}
2db9983a4   Allan Stephens   tipc: split varia...
1181
1182
1183
1184
1185
  	if (has_name) {
  		res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data);
  		if (res)
  			return res;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1186
1187
1188
  
  	return 0;
  }
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1189
  static void tipc_sk_send_ack(struct tipc_sock *tsk)
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1190
  {
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
1191
1192
  	struct sock *sk = &tsk->sk;
  	struct net *net = sock_net(sk);
a6ca10944   Ying Xue   tipc: use generic...
1193
  	struct sk_buff *skb = NULL;
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1194
  	struct tipc_msg *msg;
301bae56f   Jon Paul Maloy   tipc: merge struc...
1195
1196
  	u32 peer_port = tsk_peer_port(tsk);
  	u32 dnode = tsk_peer_node(tsk);
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1197

d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
1198
  	if (!tipc_sk_connected(sk))
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1199
  		return;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
1200
1201
1202
  	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...
1203
  	if (!skb)
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1204
  		return;
a6ca10944   Ying Xue   tipc: use generic...
1205
  	msg = buf_msg(skb);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1206
1207
1208
1209
1210
1211
1212
1213
  	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 ...
1214
  	tipc_node_xmit_skb(net, skb, dnode, msg_link_selector(msg));
739f5e4ef   Jon Paul Maloy   tipc: redefine me...
1215
  }
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1216
  static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
9bbb4ecc6   Ying Xue   tipc: standardize...
1217
1218
1219
  {
  	struct sock *sk = sock->sk;
  	DEFINE_WAIT(wait);
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1220
  	long timeo = *timeop;
4e0df4951   Parthasarathy Bhuvaragan   tipc: improve err...
1221
1222
1223
1224
  	int err = sock_error(sk);
  
  	if (err)
  		return err;
9bbb4ecc6   Ying Xue   tipc: standardize...
1225
1226
1227
  
  	for (;;) {
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
fe8e46493   Ying Xue   tipc: avoid to un...
1228
  		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
1229
  			if (sk->sk_shutdown & RCV_SHUTDOWN) {
9bbb4ecc6   Ying Xue   tipc: standardize...
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
  				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...
1240
1241
1242
  		err = -EAGAIN;
  		if (!timeo)
  			break;
143fe22f5   Erik Hugne   tipc: fix inconsi...
1243
1244
1245
  		err = sock_intr_errno(timeo);
  		if (signal_pending(current))
  			break;
4e0df4951   Parthasarathy Bhuvaragan   tipc: improve err...
1246
1247
1248
1249
  
  		err = sock_error(sk);
  		if (err)
  			break;
9bbb4ecc6   Ying Xue   tipc: standardize...
1250
1251
  	}
  	finish_wait(sk_sleep(sk), &wait);
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
1252
  	*timeop = timeo;
9bbb4ecc6   Ying Xue   tipc: standardize...
1253
1254
  	return err;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1255
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1256
   * tipc_recvmsg - receive packet-oriented message
b97bf3fd8   Per Liden   [TIPC] Initial merge
1257
   * @m: descriptor for message info
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1258
   * @buflen: length of user buffer area
b97bf3fd8   Per Liden   [TIPC] Initial merge
1259
   * @flags: receive flags
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1260
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1261
1262
1263
1264
1265
   * 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
   */
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1266
1267
  static int tipc_recvmsg(struct socket *sock, struct msghdr *m,
  			size_t buflen,	int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1268
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1269
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1270
  	struct tipc_sock *tsk = tipc_sk(sk);
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1271
1272
1273
1274
1275
  	struct sk_buff *skb;
  	struct tipc_msg *hdr;
  	bool connected = !tipc_sk_type_connectionless(sk);
  	int rc, err, hlen, dlen, copy;
  	long timeout;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1276

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1277
  	/* Catch invalid receive requests */
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1278
  	if (unlikely(!buflen))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1279
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1280
  	lock_sock(sk);
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1281
1282
  	if (unlikely(connected && sk->sk_state == TIPC_OPEN)) {
  		rc = -ENOTCONN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1283
1284
  		goto exit;
  	}
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1285
  	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1286

e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
  	do {
  		/* Look at first msg in receive queue; wait if necessary */
  		rc = tipc_wait_for_rcvmsg(sock, &timeout);
  		if (unlikely(rc))
  			goto exit;
  		skb = skb_peek(&sk->sk_receive_queue);
  		hdr = buf_msg(skb);
  		dlen = msg_data_sz(hdr);
  		hlen = msg_hdr_sz(hdr);
  		err = msg_errcode(hdr);
  		if (likely(dlen || err))
  			break;
2e84c60b7   Jon Paul Maloy   tipc: remove incl...
1299
  		tsk_advance_rx_queue(sk);
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1300
  	} while (1);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1301

e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1302
1303
1304
1305
  	/* Collect msg meta data, including error code and rejected data */
  	set_orig_addr(m, hdr);
  	rc = tipc_sk_anc_data_recv(m, hdr, tsk);
  	if (unlikely(rc))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1306
  		goto exit;
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1307
1308
1309
1310
  	/* Capture data if non-error msg, otherwise just set return value */
  	if (likely(!err)) {
  		copy = min_t(int, dlen, buflen);
  		if (unlikely(copy != dlen))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1311
  			m->msg_flags |= MSG_TRUNC;
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1312
  		rc = skb_copy_datagram_msg(skb, hlen, m, copy);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1313
  	} else {
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1314
1315
1316
1317
  		copy = 0;
  		rc = 0;
  		if (err != TIPC_CONN_SHUTDOWN && connected && !m->msg_control)
  			rc = -ECONNRESET;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1318
  	}
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1319
1320
  	if (unlikely(rc))
  		goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1321

e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1322
  	/* Caption of data or error code/rejected data was successful */
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1323
1324
  	if (unlikely(flags & MSG_PEEK))
  		goto exit;
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1325
  	tsk_advance_rx_queue(sk);
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1326
1327
1328
1329
1330
1331
1332
  	if (likely(!connected))
  		goto exit;
  
  	/* Send connection flow control ack when applicable */
  	tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen);
  	if (tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE)
  		tipc_sk_send_ack(tsk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1333
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1334
  	release_sock(sk);
e9f8b1010   Jon Paul Maloy   tipc: refactor fu...
1335
  	return rc ? rc : copy;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1336
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1337
  /**
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1338
   * tipc_recvstream - receive stream-oriented data
b97bf3fd8   Per Liden   [TIPC] Initial merge
1339
   * @m: descriptor for message info
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1340
   * @buflen: total size of user buffer area
b97bf3fd8   Per Liden   [TIPC] Initial merge
1341
   * @flags: receive flags
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1342
1343
   *
   * Used for SOCK_STREAM messages only.  If not enough data is available
b97bf3fd8   Per Liden   [TIPC] Initial merge
1344
1345
1346
1347
   * will optionally wait for more; never truncates data.
   *
   * Returns size of returned message data, errno otherwise
   */
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1348
1349
  static int tipc_recvstream(struct socket *sock, struct msghdr *m,
  			   size_t buflen, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1350
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1351
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1352
  	struct tipc_sock *tsk = tipc_sk(sk);
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1353
1354
1355
1356
1357
1358
1359
  	struct sk_buff *skb;
  	struct tipc_msg *hdr;
  	struct tipc_skb_cb *skb_cb;
  	bool peek = flags & MSG_PEEK;
  	int offset, required, copy, copied = 0;
  	int hlen, dlen, err, rc;
  	long timeout;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1360

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1361
  	/* Catch invalid receive attempts */
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1362
  	if (unlikely(!buflen))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1363
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1364
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1365

438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
1366
  	if (unlikely(sk->sk_state == TIPC_OPEN)) {
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1367
  		rc = -ENOTCONN;
9bbb4ecc6   Ying Xue   tipc: standardize...
1368
  		goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1369
  	}
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1370
1371
  	required = sock_rcvlowat(sk, flags & MSG_WAITALL, buflen);
  	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1372

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
  	do {
  		/* Look at first msg in receive queue; wait if necessary */
  		rc = tipc_wait_for_rcvmsg(sock, &timeout);
  		if (unlikely(rc))
  			break;
  		skb = skb_peek(&sk->sk_receive_queue);
  		skb_cb = TIPC_SKB_CB(skb);
  		hdr = buf_msg(skb);
  		dlen = msg_data_sz(hdr);
  		hlen = msg_hdr_sz(hdr);
  		err = msg_errcode(hdr);
0232fd0ac   Allan Stephens   tipc: Allow recei...
1384

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1385
1386
1387
1388
1389
  		/* Discard any empty non-errored (SYN-) message */
  		if (unlikely(!dlen && !err)) {
  			tsk_advance_rx_queue(sk);
  			continue;
  		}
0232fd0ac   Allan Stephens   tipc: Allow recei...
1390

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1391
1392
1393
1394
1395
1396
1397
  		/* Collect msg meta data, incl. error code and rejected data */
  		if (!copied) {
  			set_orig_addr(m, hdr);
  			rc = tipc_sk_anc_data_recv(m, hdr, tsk);
  			if (rc)
  				break;
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1398

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
  		/* Copy data if msg ok, otherwise return error/partial data */
  		if (likely(!err)) {
  			offset = skb_cb->bytes_read;
  			copy = min_t(int, dlen - offset, buflen - copied);
  			rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy);
  			if (unlikely(rc))
  				break;
  			copied += copy;
  			offset += copy;
  			if (unlikely(offset < dlen)) {
  				if (!peek)
  					skb_cb->bytes_read = offset;
  				break;
  			}
  		} else {
  			rc = 0;
  			if ((err != TIPC_CONN_SHUTDOWN) && !m->msg_control)
  				rc = -ECONNRESET;
  			if (copied || rc)
  				break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1419
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1420

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1421
1422
  		if (unlikely(peek))
  			break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1423

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1424
  		tsk_advance_rx_queue(sk);
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1425

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1426
1427
1428
1429
  		/* Send connection flow control advertisement when applicable */
  		tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen);
  		if (unlikely(tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE))
  			tipc_sk_send_ack(tsk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1430

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1431
1432
1433
  		/* Exit if all requested data or FIN/error received */
  		if (copied == buflen || err)
  			break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1434

ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1435
  	} while (!skb_queue_empty(&sk->sk_receive_queue) || copied < required);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1436
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1437
  	release_sock(sk);
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
1438
  	return copied ? copied : rc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1439
1440
1441
  }
  
  /**
f288bef46   Ying Xue   tipc: fix race/in...
1442
1443
1444
1445
1446
1447
1448
1449
1450
   * 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...
1451
  	if (skwq_has_sleeper(wq))
f288bef46   Ying Xue   tipc: fix race/in...
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  		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...
1462
  static void tipc_data_ready(struct sock *sk)
f288bef46   Ying Xue   tipc: fix race/in...
1463
1464
1465
1466
1467
  {
  	struct socket_wq *wq;
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
1ce0bf50a   Herbert Xu   net: Generalise w...
1468
  	if (skwq_has_sleeper(wq))
f288bef46   Ying Xue   tipc: fix race/in...
1469
1470
1471
1472
  		wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
  						POLLRDNORM | POLLRDBAND);
  	rcu_read_unlock();
  }
f4195d1ea   Ying Xue   tipc: avoid packe...
1473
1474
1475
1476
  static void tipc_sock_destruct(struct sock *sk)
  {
  	__skb_queue_purge(&sk->sk_receive_queue);
  }
f288bef46   Ying Xue   tipc: fix race/in...
1477
  /**
7e6c131e1   Ying Xue   tipc: consolidate...
1478
   * filter_connect - Handle all incoming messages for a connection-based socket
58ed94424   Jon Paul Maloy   tipc: align usage...
1479
   * @tsk: TIPC socket
1186adf7d   Jon Paul Maloy   tipc: simplify me...
1480
   * @skb: pointer to message buffer. Set to NULL if buffer is consumed
7e6c131e1   Ying Xue   tipc: consolidate...
1481
   *
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1482
   * Returns true if everything ok, false otherwise
7e6c131e1   Ying Xue   tipc: consolidate...
1483
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1484
  static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
7e6c131e1   Ying Xue   tipc: consolidate...
1485
  {
58ed94424   Jon Paul Maloy   tipc: align usage...
1486
  	struct sock *sk = &tsk->sk;
f2f9800d4   Ying Xue   tipc: make tipc n...
1487
  	struct net *net = sock_net(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1488
  	struct tipc_msg *hdr = buf_msg(skb);
4e0df4951   Parthasarathy Bhuvaragan   tipc: improve err...
1489
1490
  	u32 pport = msg_origport(hdr);
  	u32 pnode = msg_orignode(hdr);
7e6c131e1   Ying Xue   tipc: consolidate...
1491

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1492
1493
  	if (unlikely(msg_mcast(hdr)))
  		return false;
7e6c131e1   Ying Xue   tipc: consolidate...
1494

99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1495
1496
  	switch (sk->sk_state) {
  	case TIPC_CONNECTING:
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1497
  		/* Accept only ACK or NACK message */
4e0df4951   Parthasarathy Bhuvaragan   tipc: improve err...
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
  		if (unlikely(!msg_connected(hdr))) {
  			if (pport != tsk_peer_port(tsk) ||
  			    pnode != tsk_peer_node(tsk))
  				return false;
  
  			tipc_set_sk_state(sk, TIPC_DISCONNECTING);
  			sk->sk_err = ECONNREFUSED;
  			sk->sk_state_change(sk);
  			return true;
  		}
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1508

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1509
  		if (unlikely(msg_errcode(hdr))) {
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
1510
  			tipc_set_sk_state(sk, TIPC_DISCONNECTING);
2c8d85182   Erik Hugne   tipc: set sk_err ...
1511
  			sk->sk_err = ECONNREFUSED;
4e0df4951   Parthasarathy Bhuvaragan   tipc: improve err...
1512
  			sk->sk_state_change(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1513
  			return true;
584d24b39   Ying Xue   tipc: introduce n...
1514
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1515
  		if (unlikely(!msg_isdata(hdr))) {
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
1516
  			tipc_set_sk_state(sk, TIPC_DISCONNECTING);
dadebc002   Jon Paul Maloy   tipc: eliminate p...
1517
  			sk->sk_err = EINVAL;
4e0df4951   Parthasarathy Bhuvaragan   tipc: improve err...
1518
  			sk->sk_state_change(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1519
  			return true;
584d24b39   Ying Xue   tipc: introduce n...
1520
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1521
1522
  		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...
1523

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1524
1525
1526
1527
1528
  		/* If 'ACK+' message, add to socket receive queue */
  		if (msg_data_sz(hdr))
  			return true;
  
  		/* If empty 'ACK-' message, wake up sleeping connect() */
42b531de1   Parthasarathy Bhuvaragan   tipc: Fix missing...
1529
  		sk->sk_data_ready(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1530
1531
1532
1533
  
  		/* 'ACK-' message is neither accepted nor rejected: */
  		msg_set_dest_droppable(hdr, 1);
  		return false;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1534

438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
1535
  	case TIPC_OPEN:
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
1536
  	case TIPC_DISCONNECTING:
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
1537
1538
  		break;
  	case TIPC_LISTEN:
7e6c131e1   Ying Xue   tipc: consolidate...
1539
  		/* Accept only SYN message */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1540
1541
  		if (!msg_connected(hdr) && !(msg_errcode(hdr)))
  			return true;
7e6c131e1   Ying Xue   tipc: consolidate...
1542
  		break;
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
  	case TIPC_ESTABLISHED:
  		/* Accept only connection-based messages sent by peer */
  		if (unlikely(!tsk_peer_msg(tsk, hdr)))
  			return false;
  
  		if (unlikely(msg_errcode(hdr))) {
  			tipc_set_sk_state(sk, TIPC_DISCONNECTING);
  			/* Let timer expire on it's own */
  			tipc_node_remove_conn(net, tsk_peer_node(tsk),
  					      tsk->portid);
  			sk->sk_state_change(sk);
  		}
  		return true;
7e6c131e1   Ying Xue   tipc: consolidate...
1556
  	default:
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
1557
1558
  		pr_err("Unknown sk_state %u
  ", sk->sk_state);
7e6c131e1   Ying Xue   tipc: consolidate...
1559
  	}
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
1560

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1561
  	return false;
7e6c131e1   Ying Xue   tipc: consolidate...
1562
1563
1564
  }
  
  /**
aba79f332   Ying Xue   tipc: byte-based ...
1565
1566
   * rcvbuf_limit - get proper overload limit of socket receive queue
   * @sk: socket
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1567
   * @skb: message
aba79f332   Ying Xue   tipc: byte-based ...
1568
   *
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1569
1570
   * For connection oriented messages, irrespective of importance,
   * default queue limit is 2 MB.
aba79f332   Ying Xue   tipc: byte-based ...
1571
   *
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1572
1573
   * For connectionless messages, queue limits are based on message
   * importance as follows:
aba79f332   Ying Xue   tipc: byte-based ...
1574
   *
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1575
1576
1577
1578
   * 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 ...
1579
1580
1581
   *
   * Returns overload limit according to corresponding message importance
   */
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1582
  static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *skb)
aba79f332   Ying Xue   tipc: byte-based ...
1583
  {
10724cc7b   Jon Paul Maloy   tipc: redesign co...
1584
1585
1586
1587
1588
  	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 ...
1589

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

10724cc7b   Jon Paul Maloy   tipc: redesign co...
1593
  	return FLOWCTL_MSG_LIM;
aba79f332   Ying Xue   tipc: byte-based ...
1594
1595
1596
  }
  
  /**
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1597
1598
   * filter_rcv - validate incoming message
   * @sk: socket
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1599
   * @skb: pointer to message.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1600
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1601
1602
1603
   * Enqueues message on receive queue if acceptable; optionally handles
   * disconnect indication for a connected socket.
   *
1186adf7d   Jon Paul Maloy   tipc: simplify me...
1604
   * Called with socket lock already taken
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1605
   *
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1606
   * Returns true if message was added to socket receive queue, otherwise false
b97bf3fd8   Per Liden   [TIPC] Initial merge
1607
   */
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1608
1609
  static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
  		       struct sk_buff_head *xmitq)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1610
  {
58ed94424   Jon Paul Maloy   tipc: align usage...
1611
  	struct tipc_sock *tsk = tipc_sk(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1612
1613
1614
1615
  	struct tipc_msg *hdr = buf_msg(skb);
  	unsigned int limit = rcvbuf_limit(sk, skb);
  	int err = TIPC_OK;
  	int usr = msg_user(hdr);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1616
  	u32 onode;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1617

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1618
  	if (unlikely(msg_user(hdr) == CONN_MANAGER)) {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1619
  		tipc_sk_proto_rcv(tsk, skb, xmitq);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1620
  		return false;
1186adf7d   Jon Paul Maloy   tipc: simplify me...
1621
  	}
ec8a2e562   Jon Paul Maloy   tipc: same receiv...
1622

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1623
  	if (unlikely(usr == SOCK_WAKEUP)) {
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1624
  		onode = msg_orignode(hdr);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1625
  		kfree_skb(skb);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
1626
1627
  		u32_del(&tsk->cong_links, onode);
  		tsk->cong_link_cnt--;
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
1628
  		sk->sk_write_space(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1629
  		return false;
50100a5e3   Jon Paul Maloy   tipc: use pseudo ...
1630
  	}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1631
1632
1633
1634
1635
  	/* Drop if illegal message type */
  	if (unlikely(msg_type(hdr) > TIPC_DIRECT_MSG)) {
  		kfree_skb(skb);
  		return false;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1636

cda3696d3   Jon Paul Maloy   tipc: clean up so...
1637
  	/* Reject if wrong message type for current socket state */
c752023aa   Parthasarathy Bhuvaragan   tipc: remove sock...
1638
  	if (tipc_sk_type_connectionless(sk)) {
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1639
1640
1641
1642
1643
1644
1645
  		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
1646
1647
1648
  	}
  
  	/* Reject message if there isn't room to queue it */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1649
1650
1651
1652
  	if (unlikely(sk_rmem_alloc_get(sk) + skb->truesize >= limit)) {
  		err = TIPC_ERR_OVERLOAD;
  		goto reject;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1653

aba79f332   Ying Xue   tipc: byte-based ...
1654
  	/* Enqueue message */
ba8aebe94   Parthasarathy Bhuvaragan   tipc: rename stru...
1655
  	TIPC_SKB_CB(skb)->bytes_read = 0;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1656
1657
  	__skb_queue_tail(&sk->sk_receive_queue, skb);
  	skb_set_owner_r(skb, sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1658

676d23690   David S. Miller   net: Fix use afte...
1659
  	sk->sk_data_ready(sk);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1660
1661
1662
  	return true;
  
  reject:
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1663
1664
  	if (tipc_msg_reverse(tsk_own_node(tsk), &skb, err))
  		__skb_queue_tail(xmitq, skb);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1665
  	return false;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1666
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
1667

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1668
  /**
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1669
   * tipc_backlog_rcv - handle incoming message from backlog queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1670
   * @sk: socket
a6ca10944   Ying Xue   tipc: use generic...
1671
   * @skb: message
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1672
   *
e3a77561e   Jon Paul Maloy   tipc: split up fu...
1673
   * Caller must hold socket lock
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1674
1675
1676
   *
   * Returns 0
   */
a6ca10944   Ying Xue   tipc: use generic...
1677
  static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1678
  {
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1679
  	unsigned int truesize = skb->truesize;
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1680
1681
  	struct sk_buff_head xmitq;
  	u32 dnode, selector;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1682

f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1683
1684
1685
  	__skb_queue_head_init(&xmitq);
  
  	if (likely(filter_rcv(sk, skb, &xmitq))) {
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1686
  		atomic_add(truesize, &tipc_sk(sk)->dupl_rcvcnt);
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  		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 ...
1698
1699
1700
1701
  	return 0;
  }
  
  /**
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1702
1703
1704
1705
1706
   * 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...
1707
1708
   *
   * Caller must hold socket lock
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1709
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1710
  static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1711
  			    u32 dport, struct sk_buff_head *xmitq)
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1712
  {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1713
1714
  	unsigned long time_limit = jiffies + 2;
  	struct sk_buff *skb;
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1715
1716
  	unsigned int lim;
  	atomic_t *dcnt;
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1717
  	u32 onode;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1718
1719
  
  	while (skb_queue_len(inputq)) {
51a00daf7   Jon Paul Maloy   tipc: fix bug in ...
1720
  		if (unlikely(time_after_eq(jiffies, time_limit)))
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1721
  			return;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1722
1723
  		skb = tipc_skb_dequeue(inputq, dport);
  		if (unlikely(!skb))
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1724
1725
1726
  			return;
  
  		/* Add message directly to receive queue if possible */
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1727
  		if (!sock_owned_by_user(sk)) {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1728
  			filter_rcv(sk, skb, xmitq);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1729
  			continue;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1730
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1731
1732
  
  		/* Try backlog, compensating for double-counted bytes */
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1733
  		dcnt = &tipc_sk(sk)->dupl_rcvcnt;
7c8bcfb12   Jon Paul Maloy   tipc: re-enable c...
1734
  		if (!sk->sk_backlog.len)
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1735
1736
1737
1738
  			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...
1739
1740
  
  		/* Overload => reject message back to sender */
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1741
1742
1743
  		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...
1744
  		break;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1745
  	}
d570d8649   Jon Paul Maloy   tipc: enqueue arr...
1746
1747
1748
  }
  
  /**
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1749
1750
1751
1752
   * 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 ...
1753
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1754
  void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1755
  {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1756
  	struct sk_buff_head xmitq;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1757
  	u32 dnode, dport = 0;
9871b27f6   Erik Hugne   tipc: fix random ...
1758
  	int err;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1759
  	struct tipc_sock *tsk;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1760
  	struct sock *sk;
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1761
  	struct sk_buff *skb;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1762

f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1763
  	__skb_queue_head_init(&xmitq);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1764
  	while (skb_queue_len(inputq)) {
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1765
1766
  		dport = tipc_skb_peek_port(inputq, dport);
  		tsk = tipc_sk_lookup(net, dport);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1767

c637c1035   Jon Paul Maloy   tipc: resolve rac...
1768
1769
1770
  		if (likely(tsk)) {
  			sk = &tsk->sk;
  			if (likely(spin_trylock_bh(&sk->sk_lock.slock))) {
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1771
  				tipc_sk_enqueue(inputq, sk, dport, &xmitq);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1772
  				spin_unlock_bh(&sk->sk_lock.slock);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1773
  			}
f1d048f24   Jon Paul Maloy   tipc: fix socket ...
1774
1775
1776
1777
1778
  			/* 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...
1779
  			sock_put(sk);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1780
  			continue;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1781
  		}
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
  
  		/* 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...
1795
  			continue;
e3a77561e   Jon Paul Maloy   tipc: split up fu...
1796
  xmit:
cda3696d3   Jon Paul Maloy   tipc: clean up so...
1797
  		dnode = msg_destnode(buf_msg(skb));
af9b028e2   Jon Paul Maloy   tipc: make media ...
1798
  		tipc_node_xmit_skb(net, skb, dnode, dport);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
1799
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1800
  }
78eb3a537   Ying Xue   tipc: standardize...
1801
1802
  static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
  {
d9dc8b0f8   WANG Cong   net: fix sleeping...
1803
  	DEFINE_WAIT_FUNC(wait, woken_wake_function);
78eb3a537   Ying Xue   tipc: standardize...
1804
  	struct sock *sk = sock->sk;
78eb3a537   Ying Xue   tipc: standardize...
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
  	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);
d9dc8b0f8   WANG Cong   net: fix sleeping...
1815
  		add_wait_queue(sk_sleep(sk), &wait);
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1816
  		done = sk_wait_event(sk, timeo_p,
d9dc8b0f8   WANG Cong   net: fix sleeping...
1817
1818
  				     sk->sk_state != TIPC_CONNECTING, &wait);
  		remove_wait_queue(sk_sleep(sk), &wait);
78eb3a537   Ying Xue   tipc: standardize...
1819
1820
1821
  	} while (!done);
  	return 0;
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
1822
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1823
   * tipc_connect - establish a connection to another TIPC port
b97bf3fd8   Per Liden   [TIPC] Initial merge
1824
1825
1826
   * @sock: socket structure
   * @dest: socket address for destination port
   * @destlen: size of socket address data structure
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1827
   * @flags: file-related flags associated with socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
1828
1829
1830
   *
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1831
1832
  static int tipc_connect(struct socket *sock, struct sockaddr *dest,
  			int destlen, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1833
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1834
  	struct sock *sk = sock->sk;
f2f8036e3   Erik Hugne   tipc: add support...
1835
  	struct tipc_sock *tsk = tipc_sk(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1836
1837
  	struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
  	struct msghdr m = {NULL,};
f2f8036e3   Erik Hugne   tipc: add support...
1838
  	long timeout = (flags & O_NONBLOCK) ? 0 : tsk->conn_timeout;
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1839
  	int previous;
f2f8036e3   Erik Hugne   tipc: add support...
1840
  	int res = 0;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1841

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1842
  	lock_sock(sk);
f2f8036e3   Erik Hugne   tipc: add support...
1843
  	/* DGRAM/RDM connect(), just save the destaddr */
c752023aa   Parthasarathy Bhuvaragan   tipc: remove sock...
1844
  	if (tipc_sk_type_connectionless(sk)) {
f2f8036e3   Erik Hugne   tipc: add support...
1845
  		if (dst->family == AF_UNSPEC) {
aeda16b6a   Parthasarathy Bhuvaragan   tipc: rename tsk-...
1846
  			memset(&tsk->peer, 0, sizeof(struct sockaddr_tipc));
610600c8c   Sasha Levin   tipc: validate le...
1847
1848
  		} else if (destlen != sizeof(struct sockaddr_tipc)) {
  			res = -EINVAL;
f2f8036e3   Erik Hugne   tipc: add support...
1849
  		} else {
aeda16b6a   Parthasarathy Bhuvaragan   tipc: rename tsk-...
1850
  			memcpy(&tsk->peer, dest, destlen);
f2f8036e3   Erik Hugne   tipc: add support...
1851
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1852
1853
  		goto exit;
  	}
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1854

b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1855
1856
1857
1858
1859
1860
  	/*
  	 * 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 ...
1861
1862
1863
1864
  	if (dst->addrtype == TIPC_ADDR_MCAST) {
  		res = -EINVAL;
  		goto exit;
  	}
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1865
  	previous = sk->sk_state;
438adcaf0   Parthasarathy Bhuvaragan   tipc: create TIPC...
1866
1867
1868
  
  	switch (sk->sk_state) {
  	case TIPC_OPEN:
584d24b39   Ying Xue   tipc: introduce n...
1869
1870
1871
1872
1873
1874
1875
1876
1877
  		/* 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...
1878
  		res = __tipc_sendmsg(sock, &m, 0);
584d24b39   Ying Xue   tipc: introduce n...
1879
1880
  		if ((res < 0) && (res != -EWOULDBLOCK))
  			goto exit;
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1881
  		/* Just entered TIPC_CONNECTING state; the only
584d24b39   Ying Xue   tipc: introduce n...
1882
1883
1884
1885
  		 * difference is that return value in non-blocking
  		 * case is EINPROGRESS, rather than EALREADY.
  		 */
  		res = -EINPROGRESS;
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1886
1887
1888
1889
1890
  		/* fall thru' */
  	case TIPC_CONNECTING:
  		if (!timeout) {
  			if (previous == TIPC_CONNECTING)
  				res = -EALREADY;
78eb3a537   Ying Xue   tipc: standardize...
1891
  			goto exit;
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1892
  		}
78eb3a537   Ying Xue   tipc: standardize...
1893
1894
1895
  		timeout = msecs_to_jiffies(timeout);
  		/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
  		res = tipc_wait_for_connect(sock, &timeout);
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
1896
1897
  		break;
  	case TIPC_ESTABLISHED:
584d24b39   Ying Xue   tipc: introduce n...
1898
  		res = -EISCONN;
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
1899
1900
  		break;
  	default:
584d24b39   Ying Xue   tipc: introduce n...
1901
  		res = -EINVAL;
f40acbaf4   Parthasarathy Bhuvaragan   tipc: remove SS_C...
1902
  	}
99a208898   Parthasarathy Bhuvaragan   tipc: create TIPC...
1903

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1904
1905
  exit:
  	release_sock(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1906
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1907
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1908
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1909
   * tipc_listen - allow socket to listen for incoming connections
b97bf3fd8   Per Liden   [TIPC] Initial merge
1910
1911
   * @sock: socket structure
   * @len: (unused)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1912
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1913
1914
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1915
  static int tipc_listen(struct socket *sock, int len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1916
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1917
1918
1919
1920
  	struct sock *sk = sock->sk;
  	int res;
  
  	lock_sock(sk);
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
1921
  	res = tipc_set_sk_state(sk, TIPC_LISTEN);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1922
  	release_sock(sk);
0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
1923

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1924
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1925
  }
6398e23cd   Ying Xue   tipc: standardize...
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
  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...
1940
  		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
6398e23cd   Ying Xue   tipc: standardize...
1941
1942
1943
1944
1945
1946
1947
  			release_sock(sk);
  			timeo = schedule_timeout(timeo);
  			lock_sock(sk);
  		}
  		err = 0;
  		if (!skb_queue_empty(&sk->sk_receive_queue))
  			break;
6398e23cd   Ying Xue   tipc: standardize...
1948
1949
1950
  		err = -EAGAIN;
  		if (!timeo)
  			break;
143fe22f5   Erik Hugne   tipc: fix inconsi...
1951
1952
1953
  		err = sock_intr_errno(timeo);
  		if (signal_pending(current))
  			break;
6398e23cd   Ying Xue   tipc: standardize...
1954
1955
1956
1957
  	}
  	finish_wait(sk_sleep(sk), &wait);
  	return err;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1958
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1959
   * tipc_accept - wait for connection request
b97bf3fd8   Per Liden   [TIPC] Initial merge
1960
1961
1962
   * @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...
1963
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1964
1965
   * Returns 0 on success, errno otherwise
   */
cdfbabfb2   David Howells   net: Work around ...
1966
1967
  static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
  		       bool kern)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1968
  {
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1969
  	struct sock *new_sk, *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1970
  	struct sk_buff *buf;
301bae56f   Jon Paul Maloy   tipc: merge struc...
1971
  	struct tipc_sock *new_tsock;
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1972
  	struct tipc_msg *msg;
6398e23cd   Ying Xue   tipc: standardize...
1973
  	long timeo;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1974
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1975

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

0c288c869   Parthasarathy Bhuvaragan   tipc: create TIPC...
1978
  	if (sk->sk_state != TIPC_LISTEN) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1979
  		res = -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1980
1981
  		goto exit;
  	}
6398e23cd   Ying Xue   tipc: standardize...
1982
1983
1984
1985
  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
  	res = tipc_wait_for_accept(sock, timeo);
  	if (res)
  		goto exit;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1986
1987
  
  	buf = skb_peek(&sk->sk_receive_queue);
cdfbabfb2   David Howells   net: Work around ...
1988
  	res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, kern);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1989
1990
  	if (res)
  		goto exit;
fdd75ea8d   Stephen Smalley   net/tipc: initial...
1991
  	security_sk_clone(sock->sk, new_sock->sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1992

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

0fef8f205   Paul Gortmaker   tipc: refactor ac...
1997
1998
1999
2000
2001
2002
2003
  	/* 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...
2004
  	tsk_rej_rx_queue(new_sk);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2005
2006
  
  	/* Connect new socket to it's peer */
301bae56f   Jon Paul Maloy   tipc: merge struc...
2007
  	tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2008

301bae56f   Jon Paul Maloy   tipc: merge struc...
2009
  	tsk_set_importance(new_tsock, msg_importance(msg));
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2010
  	if (msg_named(msg)) {
301bae56f   Jon Paul Maloy   tipc: merge struc...
2011
2012
  		new_tsock->conn_type = msg_nametype(msg);
  		new_tsock->conn_instance = msg_nameinst(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2013
  	}
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2014
2015
2016
2017
2018
2019
2020
  
  	/*
  	 * 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...
2021
  		tsk_advance_rx_queue(sk);
365ad353c   Jon Paul Maloy   tipc: reduce risk...
2022
  		__tipc_sendstream(new_sock, &m, 0);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2023
2024
2025
  	} else {
  		__skb_dequeue(&sk->sk_receive_queue);
  		__skb_queue_head(&new_sk->sk_receive_queue, buf);
aba79f332   Ying Xue   tipc: byte-based ...
2026
  		skb_set_owner_r(buf, new_sk);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
2027
2028
  	}
  	release_sock(new_sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2029
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2030
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2031
2032
2033
2034
  	return res;
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
2035
   * tipc_shutdown - shutdown socket connection
b97bf3fd8   Per Liden   [TIPC] Initial merge
2036
   * @sock: socket structure
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
2037
   * @how: direction to close (must be SHUT_RDWR)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2038
2039
   *
   * Terminates connection (if necessary), then purges socket's receive queue.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2040
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
2041
2042
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
2043
  static int tipc_shutdown(struct socket *sock, int how)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2044
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2045
  	struct sock *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2046
  	int res;
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
2047
2048
  	if (how != SHUT_RDWR)
  		return -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2049

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

6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
2052
2053
  	__tipc_shutdown(sock, TIPC_CONN_SHUTDOWN);
  	sk->sk_shutdown = SEND_SHUTDOWN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2054

6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
2055
  	if (sk->sk_state == TIPC_DISCONNECTING) {
750311510   Ying Xue   tipc: wake up all...
2056
  		/* Discard any unreceived messages */
57467e562   Ying Xue   tipc: eliminate d...
2057
  		__skb_queue_purge(&sk->sk_receive_queue);
750311510   Ying Xue   tipc: wake up all...
2058
2059
2060
  
  		/* Wake up anyone sleeping in poll */
  		sk->sk_state_change(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2061
  		res = 0;
6f00089c7   Parthasarathy Bhuvaragan   tipc: remove SS_D...
2062
  	} else {
b97bf3fd8   Per Liden   [TIPC] Initial merge
2063
2064
  		res = -ENOTCONN;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2065
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2066
2067
  	return res;
  }
f2f2a96a2   Ying Xue   tipc: feed tipc s...
2068
  static void tipc_sk_timeout(unsigned long data)
572890158   Jon Paul Maloy   tipc: clean up so...
2069
  {
f2f2a96a2   Ying Xue   tipc: feed tipc s...
2070
2071
  	struct tipc_sock *tsk = (struct tipc_sock *)data;
  	struct sock *sk = &tsk->sk;
a6ca10944   Ying Xue   tipc: use generic...
2072
  	struct sk_buff *skb = NULL;
572890158   Jon Paul Maloy   tipc: clean up so...
2073
  	u32 peer_port, peer_node;
c5898636c   Jon Paul Maloy   tipc: reduce usag...
2074
  	u32 own_node = tsk_own_node(tsk);
572890158   Jon Paul Maloy   tipc: clean up so...
2075

6c9808ce0   Jon Paul Maloy   tipc: remove port...
2076
  	bh_lock_sock(sk);
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
2077
  	if (!tipc_sk_connected(sk)) {
6c9808ce0   Jon Paul Maloy   tipc: remove port...
2078
2079
  		bh_unlock_sock(sk);
  		goto exit;
572890158   Jon Paul Maloy   tipc: clean up so...
2080
  	}
301bae56f   Jon Paul Maloy   tipc: merge struc...
2081
2082
  	peer_port = tsk_peer_port(tsk);
  	peer_node = tsk_peer_node(tsk);
572890158   Jon Paul Maloy   tipc: clean up so...
2083

8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
2084
  	if (tsk->probe_unacked) {
b3be5e3e7   Erik Hugne   tipc: disconnect ...
2085
  		if (!sock_owned_by_user(sk)) {
9fd4b070f   Parthasarathy Bhuvaragan   tipc: create TIPC...
2086
  			tipc_set_sk_state(sk, TIPC_DISCONNECTING);
b3be5e3e7   Erik Hugne   tipc: disconnect ...
2087
2088
2089
2090
2091
2092
2093
  			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));
  		}
360aab6b4   Parthasarathy Bhuvaragan   tipc: remove prob...
2094
2095
  		bh_unlock_sock(sk);
  		goto exit;
572890158   Jon Paul Maloy   tipc: clean up so...
2096
  	}
360aab6b4   Parthasarathy Bhuvaragan   tipc: remove prob...
2097
2098
2099
2100
  
  	skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE,
  			      INT_H_SIZE, 0, peer_node, own_node,
  			      peer_port, tsk->portid, TIPC_OK);
8ea642ee9   Parthasarathy Bhuvaragan   tipc: create TIPC...
2101
  	tsk->probe_unacked = true;
360aab6b4   Parthasarathy Bhuvaragan   tipc: remove prob...
2102
  	sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL);
572890158   Jon Paul Maloy   tipc: clean up so...
2103
  	bh_unlock_sock(sk);
a6ca10944   Ying Xue   tipc: use generic...
2104
  	if (skb)
af9b028e2   Jon Paul Maloy   tipc: make media ...
2105
  		tipc_node_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid);
6c9808ce0   Jon Paul Maloy   tipc: remove port...
2106
  exit:
07f6c4bc0   Ying Xue   tipc: convert tip...
2107
  	sock_put(sk);
572890158   Jon Paul Maloy   tipc: clean up so...
2108
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
2109
  static int tipc_sk_publish(struct tipc_sock *tsk, uint scope,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2110
2111
  			   struct tipc_name_seq const *seq)
  {
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
2112
2113
  	struct sock *sk = &tsk->sk;
  	struct net *net = sock_net(sk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2114
2115
  	struct publication *publ;
  	u32 key;
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
2116
  	if (tipc_sk_connected(sk))
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2117
  		return -EINVAL;
07f6c4bc0   Ying Xue   tipc: convert tip...
2118
2119
  	key = tsk->portid + tsk->pub_count + 1;
  	if (key == tsk->portid)
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2120
  		return -EADDRINUSE;
f2f9800d4   Ying Xue   tipc: make tipc n...
2121
  	publ = tipc_nametbl_publish(net, seq->type, seq->lower, seq->upper,
07f6c4bc0   Ying Xue   tipc: convert tip...
2122
  				    scope, tsk->portid, key);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2123
2124
  	if (unlikely(!publ))
  		return -EINVAL;
301bae56f   Jon Paul Maloy   tipc: merge struc...
2125
2126
2127
  	list_add(&publ->pport_list, &tsk->publications);
  	tsk->pub_count++;
  	tsk->published = 1;
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2128
2129
  	return 0;
  }
301bae56f   Jon Paul Maloy   tipc: merge struc...
2130
  static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2131
2132
  			    struct tipc_name_seq const *seq)
  {
f2f9800d4   Ying Xue   tipc: make tipc n...
2133
  	struct net *net = sock_net(&tsk->sk);
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2134
2135
2136
  	struct publication *publ;
  	struct publication *safe;
  	int rc = -EINVAL;
301bae56f   Jon Paul Maloy   tipc: merge struc...
2137
  	list_for_each_entry_safe(publ, safe, &tsk->publications, pport_list) {
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2138
2139
2140
2141
2142
2143
2144
2145
2146
  		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...
2147
  			tipc_nametbl_withdraw(net, publ->type, publ->lower,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2148
2149
2150
2151
  					      publ->ref, publ->key);
  			rc = 0;
  			break;
  		}
f2f9800d4   Ying Xue   tipc: make tipc n...
2152
  		tipc_nametbl_withdraw(net, publ->type, publ->lower,
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2153
2154
2155
  				      publ->ref, publ->key);
  		rc = 0;
  	}
301bae56f   Jon Paul Maloy   tipc: merge struc...
2156
2157
  	if (list_empty(&tsk->publications))
  		tsk->published = 0;
0fc87aaeb   Jon Paul Maloy   tipc: remove sour...
2158
2159
  	return rc;
  }
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2160
2161
2162
  /* 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...
2163
  void tipc_sk_reinit(struct net *net)
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2164
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2165
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
40f9f4397   Herbert Xu   tipc: Fix tipc_sk...
2166
  	struct rhashtable_iter iter;
07f6c4bc0   Ying Xue   tipc: convert tip...
2167
  	struct tipc_sock *tsk;
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2168
  	struct tipc_msg *msg;
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2169

40f9f4397   Herbert Xu   tipc: Fix tipc_sk...
2170
2171
2172
2173
  	rhashtable_walk_enter(&tn->sk_rht, &iter);
  
  	do {
  		tsk = ERR_PTR(rhashtable_walk_start(&iter));
6c7e983b2   Bob Peterson   tipc: Fix tipc_sk...
2174
2175
  		if (IS_ERR(tsk))
  			goto walk_stop;
40f9f4397   Herbert Xu   tipc: Fix tipc_sk...
2176
2177
  
  		while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) {
07f6c4bc0   Ying Xue   tipc: convert tip...
2178
2179
  			spin_lock_bh(&tsk->sk.sk_lock.slock);
  			msg = &tsk->phdr;
347475395   Ying Xue   tipc: make tipc n...
2180
2181
  			msg_set_prevnode(msg, tn->own_addr);
  			msg_set_orignode(msg, tn->own_addr);
07f6c4bc0   Ying Xue   tipc: convert tip...
2182
2183
  			spin_unlock_bh(&tsk->sk.sk_lock.slock);
  		}
6c7e983b2   Bob Peterson   tipc: Fix tipc_sk...
2184
  walk_stop:
40f9f4397   Herbert Xu   tipc: Fix tipc_sk...
2185
2186
  		rhashtable_walk_stop(&iter);
  	} while (tsk == ERR_PTR(-EAGAIN));
8fed734df   Cong Wang   tipc: fix a missi...
2187
2188
  
  	rhashtable_walk_exit(&iter);
5a9ee0be3   Jon Paul Maloy   tipc: use registr...
2189
  }
e05b31f4b   Ying Xue   tipc: make tipc s...
2190
  static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2191
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2192
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
07f6c4bc0   Ying Xue   tipc: convert tip...
2193
  	struct tipc_sock *tsk;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2194

07f6c4bc0   Ying Xue   tipc: convert tip...
2195
  	rcu_read_lock();
6cca7289d   Herbert Xu   tipc: Use inlined...
2196
  	tsk = rhashtable_lookup_fast(&tn->sk_rht, &portid, tsk_rht_params);
07f6c4bc0   Ying Xue   tipc: convert tip...
2197
2198
2199
  	if (tsk)
  		sock_hold(&tsk->sk);
  	rcu_read_unlock();
808d90f9c   Jon Paul Maloy   tipc: remove file...
2200

07f6c4bc0   Ying Xue   tipc: convert tip...
2201
  	return tsk;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2202
  }
07f6c4bc0   Ying Xue   tipc: convert tip...
2203
  static int tipc_sk_insert(struct tipc_sock *tsk)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2204
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2205
2206
2207
  	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...
2208
2209
  	u32 remaining = (TIPC_MAX_PORT - TIPC_MIN_PORT) + 1;
  	u32 portid = prandom_u32() % remaining + TIPC_MIN_PORT;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2210

07f6c4bc0   Ying Xue   tipc: convert tip...
2211
2212
2213
2214
2215
2216
  	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...
2217
2218
  		if (!rhashtable_lookup_insert_fast(&tn->sk_rht, &tsk->node,
  						   tsk_rht_params))
07f6c4bc0   Ying Xue   tipc: convert tip...
2219
2220
  			return 0;
  		sock_put(&tsk->sk);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2221
  	}
07f6c4bc0   Ying Xue   tipc: convert tip...
2222
  	return -1;
808d90f9c   Jon Paul Maloy   tipc: remove file...
2223
  }
07f6c4bc0   Ying Xue   tipc: convert tip...
2224
  static void tipc_sk_remove(struct tipc_sock *tsk)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2225
  {
07f6c4bc0   Ying Xue   tipc: convert tip...
2226
  	struct sock *sk = &tsk->sk;
e05b31f4b   Ying Xue   tipc: make tipc s...
2227
  	struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2228

6cca7289d   Herbert Xu   tipc: Use inlined...
2229
  	if (!rhashtable_remove_fast(&tn->sk_rht, &tsk->node, tsk_rht_params)) {
41c6d650f   Reshetova, Elena   net: convert sock...
2230
  		WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
07f6c4bc0   Ying Xue   tipc: convert tip...
2231
  		__sock_put(sk);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2232
  	}
808d90f9c   Jon Paul Maloy   tipc: remove file...
2233
  }
6cca7289d   Herbert Xu   tipc: Use inlined...
2234
2235
2236
2237
2238
  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...
2239
2240
  	.max_size = 1048576,
  	.min_size = 256,
b5e2c150a   Thomas Graf   rhashtable: Disab...
2241
  	.automatic_shrinking = true,
6cca7289d   Herbert Xu   tipc: Use inlined...
2242
  };
e05b31f4b   Ying Xue   tipc: make tipc s...
2243
  int tipc_sk_rht_init(struct net *net)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2244
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2245
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
6cca7289d   Herbert Xu   tipc: Use inlined...
2246
2247
  
  	return rhashtable_init(&tn->sk_rht, &tsk_rht_params);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2248
  }
e05b31f4b   Ying Xue   tipc: make tipc s...
2249
  void tipc_sk_rht_destroy(struct net *net)
808d90f9c   Jon Paul Maloy   tipc: remove file...
2250
  {
e05b31f4b   Ying Xue   tipc: make tipc s...
2251
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
07f6c4bc0   Ying Xue   tipc: convert tip...
2252
2253
  	/* Wait for socket readers to complete */
  	synchronize_net();
808d90f9c   Jon Paul Maloy   tipc: remove file...
2254

e05b31f4b   Ying Xue   tipc: make tipc s...
2255
  	rhashtable_destroy(&tn->sk_rht);
808d90f9c   Jon Paul Maloy   tipc: remove file...
2256
2257
2258
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
2259
   * tipc_setsockopt - set socket option
b97bf3fd8   Per Liden   [TIPC] Initial merge
2260
2261
2262
2263
2264
   * @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...
2265
2266
   *
   * For stream sockets only, accepts and ignores all IPPROTO_TCP options
b97bf3fd8   Per Liden   [TIPC] Initial merge
2267
   * (to ease compatibility).
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2268
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
2269
2270
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
2271
2272
  static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
  			   char __user *ov, unsigned int ol)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2273
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2274
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
2275
  	struct tipc_sock *tsk = tipc_sk(sk);
01fd12bb1   Jon Paul Maloy   tipc: make replic...
2276
  	u32 value = 0;
a08ef4768   Dan Carpenter   tipc: uninitializ...
2277
  	int res = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2278

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2279
2280
  	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
  		return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
2281
2282
  	if (lvl != SOL_TIPC)
  		return -ENOPROTOOPT;
01fd12bb1   Jon Paul Maloy   tipc: make replic...
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
  
  	switch (opt) {
  	case TIPC_IMPORTANCE:
  	case TIPC_SRC_DROPPABLE:
  	case TIPC_DEST_DROPPABLE:
  	case TIPC_CONN_TIMEOUT:
  		if (ol < sizeof(value))
  			return -EINVAL;
  		res = get_user(value, (u32 __user *)ov);
  		if (res)
  			return res;
  		break;
  	default:
  		if (ov || ol)
  			return -EINVAL;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
2299

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
2300
  	lock_sock(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2301

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

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

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

25860c3bd   Paul Gortmaker   tipc: recode gets...
2392
2393
2394
2395
2396
2397
2398
  	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
2399
  }
f2f9800d4   Ying Xue   tipc: make tipc n...
2400
  static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2401
  {
f2f9800d4   Ying Xue   tipc: make tipc n...
2402
  	struct sock *sk = sock->sk;
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2403
2404
2405
2406
2407
2408
2409
  	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...
2410
2411
  		if (!tipc_node_get_linkname(sock_net(sk),
  					    lnr.bearer_id & 0xffff, lnr.peer,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2412
2413
2414
2415
2416
2417
  					    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...
2418
2419
2420
2421
  	default:
  		return -ENOIOCTLCMD;
  	}
  }
70b03759e   Erik Hugne   tipc: add support...
2422
2423
2424
2425
  static int tipc_socketpair(struct socket *sock1, struct socket *sock2)
  {
  	struct tipc_sock *tsk2 = tipc_sk(sock2->sk);
  	struct tipc_sock *tsk1 = tipc_sk(sock1->sk);
66bc1e8d5   Erik Hugne   tipc: allow rdm/d...
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
  	u32 onode = tipc_own_addr(sock_net(sock1->sk));
  
  	tsk1->peer.family = AF_TIPC;
  	tsk1->peer.addrtype = TIPC_ADDR_ID;
  	tsk1->peer.scope = TIPC_NODE_SCOPE;
  	tsk1->peer.addr.id.ref = tsk2->portid;
  	tsk1->peer.addr.id.node = onode;
  	tsk2->peer.family = AF_TIPC;
  	tsk2->peer.addrtype = TIPC_ADDR_ID;
  	tsk2->peer.scope = TIPC_NODE_SCOPE;
  	tsk2->peer.addr.id.ref = tsk1->portid;
  	tsk2->peer.addr.id.node = onode;
  
  	tipc_sk_finish_conn(tsk1, tsk2->portid, onode);
  	tipc_sk_finish_conn(tsk2, tsk1->portid, onode);
70b03759e   Erik Hugne   tipc: add support...
2441
2442
  	return 0;
  }
ae86b9e38   Ben Hutchings   net: Fix non-kern...
2443
  /* Protocol switches for the various types of TIPC sockets */
bca65eae3   Florian Westphal   [TIPC]: declare p...
2444
  static const struct proto_ops msg_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2445
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2446
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
2447
2448
2449
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
66bc1e8d5   Erik Hugne   tipc: allow rdm/d...
2450
  	.socketpair	= tipc_socketpair,
245f3d342   Ying Xue   tipc: Simplify pr...
2451
  	.accept		= sock_no_accept,
247f0f3c3   Ying Xue   tipc: align tipc ...
2452
2453
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2454
  	.ioctl		= tipc_ioctl,
245f3d342   Ying Xue   tipc: Simplify pr...
2455
  	.listen		= sock_no_listen,
247f0f3c3   Ying Xue   tipc: align tipc ...
2456
2457
2458
2459
2460
  	.shutdown	= tipc_shutdown,
  	.setsockopt	= tipc_setsockopt,
  	.getsockopt	= tipc_getsockopt,
  	.sendmsg	= tipc_sendmsg,
  	.recvmsg	= tipc_recvmsg,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2461
2462
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
2463
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
2464
  static const struct proto_ops packet_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2465
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2466
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
2467
2468
2469
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
70b03759e   Erik Hugne   tipc: add support...
2470
  	.socketpair	= tipc_socketpair,
247f0f3c3   Ying Xue   tipc: align tipc ...
2471
2472
2473
  	.accept		= tipc_accept,
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2474
  	.ioctl		= tipc_ioctl,
247f0f3c3   Ying Xue   tipc: align tipc ...
2475
2476
2477
2478
2479
2480
  	.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...
2481
2482
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
2483
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
2484
  static const struct proto_ops stream_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2485
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2486
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
2487
2488
2489
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
70b03759e   Erik Hugne   tipc: add support...
2490
  	.socketpair	= tipc_socketpair,
247f0f3c3   Ying Xue   tipc: align tipc ...
2491
2492
2493
  	.accept		= tipc_accept,
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
2494
  	.ioctl		= tipc_ioctl,
247f0f3c3   Ying Xue   tipc: align tipc ...
2495
2496
2497
2498
  	.listen		= tipc_listen,
  	.shutdown	= tipc_shutdown,
  	.setsockopt	= tipc_setsockopt,
  	.getsockopt	= tipc_getsockopt,
365ad353c   Jon Paul Maloy   tipc: reduce risk...
2499
  	.sendmsg	= tipc_sendstream,
ec8a09fbb   Jon Paul Maloy   tipc: refactor fu...
2500
  	.recvmsg	= tipc_recvstream,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2501
2502
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
2503
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
2504
  static const struct net_proto_family tipc_family_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
2505
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
2506
  	.family		= AF_TIPC,
c5fa7b3cf   Ying Xue   tipc: introduce n...
2507
  	.create		= tipc_sk_create
b97bf3fd8   Per Liden   [TIPC] Initial merge
2508
2509
2510
2511
2512
  };
  
  static struct proto tipc_proto = {
  	.name		= "TIPC",
  	.owner		= THIS_MODULE,
cc79dd1ba   Ying Xue   tipc: change sock...
2513
2514
  	.obj_size	= sizeof(struct tipc_sock),
  	.sysctl_rmem	= sysctl_tipc_rmem
b97bf3fd8   Per Liden   [TIPC] Initial merge
2515
2516
2517
  };
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
2518
   * tipc_socket_init - initialize TIPC socket interface
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2519
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
2520
2521
   * Returns 0 on success, errno otherwise
   */
4323add67   Per Liden   [TIPC] Avoid poll...
2522
  int tipc_socket_init(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2523
2524
  {
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2525
  	res = proto_register(&tipc_proto, 1);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2526
  	if (res) {
2cf8aa19f   Erik Hugne   tipc: use standar...
2527
2528
  		pr_err("Failed to register TIPC protocol type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
2529
2530
2531
2532
2533
  		goto out;
  	}
  
  	res = sock_register(&tipc_family_ops);
  	if (res) {
2cf8aa19f   Erik Hugne   tipc: use standar...
2534
2535
  		pr_err("Failed to register TIPC socket type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
2536
2537
2538
  		proto_unregister(&tipc_proto);
  		goto out;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
2539
2540
2541
2542
2543
   out:
  	return res;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
2544
   * tipc_socket_stop - stop TIPC socket interface
b97bf3fd8   Per Liden   [TIPC] Initial merge
2545
   */
4323add67   Per Liden   [TIPC] Avoid poll...
2546
  void tipc_socket_stop(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2547
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
2548
2549
2550
  	sock_unregister(tipc_family_ops.family);
  	proto_unregister(&tipc_proto);
  }
34b78a127   Richard Alpe   tipc: add sock du...
2551
2552
  
  /* Caller should hold socket lock for the passed tipc socket. */
d8182804c   Richard Alpe   tipc: fix sparse ...
2553
  static int __tipc_nl_add_sk_con(struct sk_buff *skb, struct tipc_sock *tsk)
34b78a127   Richard Alpe   tipc: add sock du...
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
  {
  	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 ...
2588
2589
  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...
2590
2591
2592
2593
  {
  	int err;
  	void *hdr;
  	struct nlattr *attrs;
347475395   Ying Xue   tipc: make tipc n...
2594
2595
  	struct net *net = sock_net(skb->sk);
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
2596
  	struct sock *sk = &tsk->sk;
34b78a127   Richard Alpe   tipc: add sock du...
2597
2598
  
  	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
bfb3e5dd8   Richard Alpe   tipc: move and re...
2599
  			  &tipc_genl_family, NLM_F_MULTI, TIPC_NL_SOCK_GET);
34b78a127   Richard Alpe   tipc: add sock du...
2600
2601
2602
2603
2604
2605
  	if (!hdr)
  		goto msg_cancel;
  
  	attrs = nla_nest_start(skb, TIPC_NLA_SOCK);
  	if (!attrs)
  		goto genlmsg_cancel;
07f6c4bc0   Ying Xue   tipc: convert tip...
2606
  	if (nla_put_u32(skb, TIPC_NLA_SOCK_REF, tsk->portid))
34b78a127   Richard Alpe   tipc: add sock du...
2607
  		goto attr_msg_cancel;
347475395   Ying Xue   tipc: make tipc n...
2608
  	if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tn->own_addr))
34b78a127   Richard Alpe   tipc: add sock du...
2609
  		goto attr_msg_cancel;
d6fb7e9c9   Parthasarathy Bhuvaragan   tipc: remove tsk-...
2610
  	if (tipc_sk_connected(sk)) {
34b78a127   Richard Alpe   tipc: add sock du...
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
  		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...
2635
2636
  	const struct bucket_table *tbl;
  	struct rhash_head *pos;
e05b31f4b   Ying Xue   tipc: make tipc s...
2637
2638
  	struct net *net = sock_net(skb->sk);
  	struct tipc_net *tn = net_generic(net, tipc_net_id);
d6e164e32   Richard Alpe   tipc: fix socket ...
2639
2640
  	u32 tbl_id = cb->args[0];
  	u32 prev_portid = cb->args[1];
34b78a127   Richard Alpe   tipc: add sock du...
2641

07f6c4bc0   Ying Xue   tipc: convert tip...
2642
  	rcu_read_lock();
e05b31f4b   Ying Xue   tipc: make tipc s...
2643
  	tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht);
d6e164e32   Richard Alpe   tipc: fix socket ...
2644
2645
  	for (; tbl_id < tbl->size; tbl_id++) {
  		rht_for_each_entry_rcu(tsk, pos, tbl, tbl_id, node) {
07f6c4bc0   Ying Xue   tipc: convert tip...
2646
  			spin_lock_bh(&tsk->sk.sk_lock.slock);
d6e164e32   Richard Alpe   tipc: fix socket ...
2647
2648
2649
2650
  			if (prev_portid && prev_portid != tsk->portid) {
  				spin_unlock_bh(&tsk->sk.sk_lock.slock);
  				continue;
  			}
07f6c4bc0   Ying Xue   tipc: convert tip...
2651
  			err = __tipc_nl_add_sk(skb, cb, tsk);
d6e164e32   Richard Alpe   tipc: fix socket ...
2652
2653
2654
2655
2656
2657
  			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...
2658
  			spin_unlock_bh(&tsk->sk.sk_lock.slock);
07f6c4bc0   Ying Xue   tipc: convert tip...
2659
  		}
34b78a127   Richard Alpe   tipc: add sock du...
2660
  	}
d6e164e32   Richard Alpe   tipc: fix socket ...
2661
  out:
07f6c4bc0   Ying Xue   tipc: convert tip...
2662
  	rcu_read_unlock();
d6e164e32   Richard Alpe   tipc: fix socket ...
2663
2664
  	cb->args[0] = tbl_id;
  	cb->args[1] = prev_portid;
34b78a127   Richard Alpe   tipc: add sock du...
2665
2666
2667
  
  	return skb->len;
  }
1a1a143da   Richard Alpe   tipc: add publica...
2668
2669
  
  /* Caller should hold socket lock for the passed tipc socket. */
d8182804c   Richard Alpe   tipc: fix sparse ...
2670
2671
2672
  static int __tipc_nl_add_sk_publ(struct sk_buff *skb,
  				 struct netlink_callback *cb,
  				 struct publication *publ)
1a1a143da   Richard Alpe   tipc: add publica...
2673
2674
2675
2676
2677
  {
  	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...
2678
  			  &tipc_genl_family, NLM_F_MULTI, TIPC_NL_PUBL_GET);
1a1a143da   Richard Alpe   tipc: add publica...
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
  	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 ...
2709
2710
2711
  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...
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
  {
  	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...
2752
  	u32 tsk_portid = cb->args[0];
1a1a143da   Richard Alpe   tipc: add publica...
2753
2754
  	u32 last_publ = cb->args[1];
  	u32 done = cb->args[2];
e05b31f4b   Ying Xue   tipc: make tipc s...
2755
  	struct net *net = sock_net(skb->sk);
1a1a143da   Richard Alpe   tipc: add publica...
2756
  	struct tipc_sock *tsk;
07f6c4bc0   Ying Xue   tipc: convert tip...
2757
  	if (!tsk_portid) {
1a1a143da   Richard Alpe   tipc: add publica...
2758
2759
2760
2761
2762
2763
  		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...
2764
2765
  		if (!attrs[TIPC_NLA_SOCK])
  			return -EINVAL;
1a1a143da   Richard Alpe   tipc: add publica...
2766
2767
  		err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX,
  				       attrs[TIPC_NLA_SOCK],
fceb6435e   Johannes Berg   netlink: pass ext...
2768
  				       tipc_nl_sock_policy, NULL);
1a1a143da   Richard Alpe   tipc: add publica...
2769
2770
2771
2772
2773
  		if (err)
  			return err;
  
  		if (!sock[TIPC_NLA_SOCK_REF])
  			return -EINVAL;
07f6c4bc0   Ying Xue   tipc: convert tip...
2774
  		tsk_portid = nla_get_u32(sock[TIPC_NLA_SOCK_REF]);
1a1a143da   Richard Alpe   tipc: add publica...
2775
2776
2777
2778
  	}
  
  	if (done)
  		return 0;
e05b31f4b   Ying Xue   tipc: make tipc s...
2779
  	tsk = tipc_sk_lookup(net, tsk_portid);
1a1a143da   Richard Alpe   tipc: add publica...
2780
2781
2782
2783
2784
2785
2786
2787
  	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...
2788
  	sock_put(&tsk->sk);
1a1a143da   Richard Alpe   tipc: add publica...
2789

07f6c4bc0   Ying Xue   tipc: convert tip...
2790
  	cb->args[0] = tsk_portid;
1a1a143da   Richard Alpe   tipc: add publica...
2791
2792
2793
2794
2795
  	cb->args[1] = last_publ;
  	cb->args[2] = done;
  
  	return skb->len;
  }