Blame view

net/tipc/socket.c 51.9 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
   *
8826cde65   Jon Paul Maloy   tipc: aggregate p...
4
   * Copyright (c) 2001-2007, 2012-2014, 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.
   */
b97bf3fd8   Per Liden   [TIPC] Initial merge
36
  #include "core.h"
d265fef6d   Allan Stephens   tipc: Remove obso...
37
  #include "port.h"
78acb1f9b   Erik Hugne   tipc: add ioctl t...
38
  #include "node.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
39

2cf8aa19f   Erik Hugne   tipc: use standar...
40
  #include <linux/export.h>
8db1bae30   Jon Paul Maloy   tipc: separate bu...
41
  #include "link.h"
2cf8aa19f   Erik Hugne   tipc: use standar...
42

b97bf3fd8   Per Liden   [TIPC] Initial merge
43
44
  #define SS_LISTENING	-1	/* socket is listening */
  #define SS_READY	-2	/* socket is connectionless */
3654ea02f   Allan Stephens   [TIPC]: Improve s...
45
  #define CONN_TIMEOUT_DEFAULT	8000	/* default connect timeout = 8s */
b97bf3fd8   Per Liden   [TIPC] Initial merge
46

4f4482dcd   Jon Paul Maloy   tipc: compensate ...
47
  static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb);
676d23690   David S. Miller   net: Fix use afte...
48
  static void tipc_data_ready(struct sock *sk);
f288bef46   Ying Xue   tipc: fix race/in...
49
  static void tipc_write_space(struct sock *sk);
247f0f3c3   Ying Xue   tipc: align tipc ...
50
51
  static int tipc_release(struct socket *sock);
  static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags);
b97bf3fd8   Per Liden   [TIPC] Initial merge
52

bca65eae3   Florian Westphal   [TIPC]: declare p...
53
54
55
  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
56
57
  
  static struct proto tipc_proto;
c5fa7b3cf   Ying Xue   tipc: introduce n...
58
  static struct proto tipc_proto_kern;
b97bf3fd8   Per Liden   [TIPC] Initial merge
59

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
60
  /*
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
   * Revised TIPC socket locking policy:
   *
   * Most socket operations take the standard socket lock when they start
   * and hold it until they finish (or until they need to sleep).  Acquiring
   * this lock grants the owner exclusive access to the fields of the socket
   * data structures, with the exception of the backlog queue.  A few socket
   * operations can be done without taking the socket lock because they only
   * read socket information that never changes during the life of the socket.
   *
   * Socket operations may acquire the lock for the associated TIPC port if they
   * need to perform an operation on the port.  If any routine needs to acquire
   * both the socket lock and the port lock it must take the socket lock first
   * to avoid the risk of deadlock.
   *
   * The dispatcher handling incoming messages cannot grab the socket lock in
   * the standard fashion, since invoked it runs at the BH level and cannot block.
   * Instead, it checks to see if the socket lock is currently owned by someone,
   * and either handles the message itself or adds it to the socket's backlog
   * queue; in the latter case the queued message is processed once the process
   * owning the socket lock releases it.
   *
   * NOTE: Releasing the socket lock while an operation is sleeping overcomes
   * the problem of a blocked socket operation preventing any other operations
   * from occurring.  However, applications must be careful if they have
   * multiple threads trying to send (or receive) on the same socket, as these
   * operations might interfere with each other.  For example, doing a connect
   * and a receive at the same time might allow the receive to consume the
   * ACK message meant for the connect.  While additional work could be done
   * to try and overcome this, it doesn't seem to be worthwhile at the present.
   *
   * NOTE: Releasing the socket lock while an operation is sleeping also ensures
   * that another operation that must be performed in a non-blocking manner is
   * not delayed for very long because the lock has already been taken.
   *
   * NOTE: This code assumes that certain fields of a port/socket pair are
   * constant over its lifetime; such fields can be examined without taking
   * the socket lock and/or port lock, and do not need to be re-read even
   * after resuming processing after waiting.  These fields include:
   *   - socket type
   *   - pointer to socket sk structure (aka tipc_sock structure)
   *   - pointer to port structure
   *   - port reference
   */
8826cde65   Jon Paul Maloy   tipc: aggregate p...
104
  #include "socket.h"
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
105
106
107
108
  /**
   * advance_rx_queue - discard first buffer in socket receive queue
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
109
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
110
  static void advance_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
111
  {
5f6d9123f   Allan Stephens   tipc: Eliminate t...
112
  	kfree_skb(__skb_dequeue(&sk->sk_receive_queue));
b97bf3fd8   Per Liden   [TIPC] Initial merge
113
  }
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
114
  /**
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
115
116
117
   * reject_rx_queue - reject all buffers in socket receive queue
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
118
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
119
  static void reject_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
120
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
121
  	struct sk_buff *buf;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
122
  	u32 dnode;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
123

8db1bae30   Jon Paul Maloy   tipc: separate bu...
124
125
126
127
  	while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
  		if (tipc_msg_reverse(buf, &dnode, TIPC_ERR_NO_PORT))
  			tipc_link_xmit2(buf, dnode, 0);
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
128
129
130
  }
  
  /**
c5fa7b3cf   Ying Xue   tipc: introduce n...
131
   * tipc_sk_create - create a TIPC socket
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
132
   * @net: network namespace (must be default network)
b97bf3fd8   Per Liden   [TIPC] Initial merge
133
134
   * @sock: pre-allocated socket structure
   * @protocol: protocol indicator (must be 0)
3f378b684   Eric Paris   net: pass kern to...
135
   * @kern: caused by kernel or by userspace?
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
136
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
137
138
   * This routine creates additional data structures used by the TIPC socket,
   * initializes them, and links them together.
b97bf3fd8   Per Liden   [TIPC] Initial merge
139
140
141
   *
   * Returns 0 on success, errno otherwise
   */
58ed94424   Jon Paul Maloy   tipc: align usage...
142
143
  static int tipc_sk_create(struct net *net, struct socket *sock,
  			  int protocol, int kern)
b97bf3fd8   Per Liden   [TIPC] Initial merge
144
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
145
146
  	const struct proto_ops *ops;
  	socket_state state;
b97bf3fd8   Per Liden   [TIPC] Initial merge
147
  	struct sock *sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
148
149
150
  	struct tipc_sock *tsk;
  	struct tipc_port *port;
  	u32 ref;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
151
152
  
  	/* Validate arguments */
b97bf3fd8   Per Liden   [TIPC] Initial merge
153
154
  	if (unlikely(protocol != 0))
  		return -EPROTONOSUPPORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
155
156
  	switch (sock->type) {
  	case SOCK_STREAM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
157
158
  		ops = &stream_ops;
  		state = SS_UNCONNECTED;
b97bf3fd8   Per Liden   [TIPC] Initial merge
159
160
  		break;
  	case SOCK_SEQPACKET:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
161
162
  		ops = &packet_ops;
  		state = SS_UNCONNECTED;
b97bf3fd8   Per Liden   [TIPC] Initial merge
163
164
  		break;
  	case SOCK_DGRAM:
b97bf3fd8   Per Liden   [TIPC] Initial merge
165
  	case SOCK_RDM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
166
167
  		ops = &msg_ops;
  		state = SS_READY;
b97bf3fd8   Per Liden   [TIPC] Initial merge
168
  		break;
499786516   Allan Stephens   [TIPC]: Improved ...
169
  	default:
499786516   Allan Stephens   [TIPC]: Improved ...
170
  		return -EPROTOTYPE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
171
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
172
  	/* Allocate socket's protocol area */
c5fa7b3cf   Ying Xue   tipc: introduce n...
173
174
175
176
  	if (!kern)
  		sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto);
  	else
  		sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto_kern);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
177
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
178
  		return -ENOMEM;
b97bf3fd8   Per Liden   [TIPC] Initial merge
179

58ed94424   Jon Paul Maloy   tipc: align usage...
180
181
182
183
184
185
186
  	tsk = tipc_sk(sk);
  	port = &tsk->port;
  
  	ref = tipc_port_init(port, TIPC_LOW_IMPORTANCE);
  	if (!ref) {
  		pr_warn("Socket registration failed, ref. table exhausted
  ");
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
187
188
189
  		sk_free(sk);
  		return -ENOMEM;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
190

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
191
  	/* Finish initializing socket data structures */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
192
193
  	sock->ops = ops;
  	sock->state = state;
b97bf3fd8   Per Liden   [TIPC] Initial merge
194

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
195
  	sock_init_data(sock, sk);
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
196
  	sk->sk_backlog_rcv = tipc_backlog_rcv;
cc79dd1ba   Ying Xue   tipc: change sock...
197
  	sk->sk_rcvbuf = sysctl_tipc_rmem[1];
f288bef46   Ying Xue   tipc: fix race/in...
198
199
  	sk->sk_data_ready = tipc_data_ready;
  	sk->sk_write_space = tipc_write_space;
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
200
201
  	tsk->conn_timeout = CONN_TIMEOUT_DEFAULT;
  	atomic_set(&tsk->dupl_rcvcnt, 0);
58ed94424   Jon Paul Maloy   tipc: align usage...
202
  	tipc_port_unlock(port);
7ef43ebaa   Allan Stephens   tipc: Fix race co...
203

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
204
  	if (sock->state == SS_READY) {
58ed94424   Jon Paul Maloy   tipc: align usage...
205
  		tipc_port_set_unreturnable(port, true);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
206
  		if (sock->type == SOCK_DGRAM)
58ed94424   Jon Paul Maloy   tipc: align usage...
207
  			tipc_port_set_unreliable(port, true);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
208
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
209
210
211
212
  	return 0;
  }
  
  /**
c5fa7b3cf   Ying Xue   tipc: introduce n...
213
214
215
216
217
218
219
220
221
222
223
224
225
   * tipc_sock_create_local - create TIPC socket from inside TIPC module
   * @type: socket type - SOCK_RDM or SOCK_SEQPACKET
   *
   * We cannot use sock_creat_kern here because it bumps module user count.
   * Since socket owner and creator is the same module we must make sure
   * that module count remains zero for module local sockets, otherwise
   * we cannot do rmmod.
   *
   * Returns 0 on success, errno otherwise
   */
  int tipc_sock_create_local(int type, struct socket **res)
  {
  	int rc;
c5fa7b3cf   Ying Xue   tipc: introduce n...
226
227
228
229
230
231
232
233
  
  	rc = sock_create_lite(AF_TIPC, type, 0, res);
  	if (rc < 0) {
  		pr_err("Failed to create kernel socket
  ");
  		return rc;
  	}
  	tipc_sk_create(&init_net, *res, 0, 1);
c5fa7b3cf   Ying Xue   tipc: introduce n...
234
235
236
237
238
239
240
241
242
243
244
245
  	return 0;
  }
  
  /**
   * tipc_sock_release_local - release socket created by tipc_sock_create_local
   * @sock: the socket to be released.
   *
   * Module reference count is not incremented when such sockets are created,
   * so we must keep it from being decremented when they are released.
   */
  void tipc_sock_release_local(struct socket *sock)
  {
247f0f3c3   Ying Xue   tipc: align tipc ...
246
  	tipc_release(sock);
c5fa7b3cf   Ying Xue   tipc: introduce n...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  	sock->ops = NULL;
  	sock_release(sock);
  }
  
  /**
   * tipc_sock_accept_local - accept a connection on a socket created
   * with tipc_sock_create_local. Use this function to avoid that
   * module reference count is inadvertently incremented.
   *
   * @sock:    the accepting socket
   * @newsock: reference to the new socket to be created
   * @flags:   socket flags
   */
  
  int tipc_sock_accept_local(struct socket *sock, struct socket **newsock,
ae8509c42   Paul Gortmaker   tipc: cosmetic re...
262
  			   int flags)
c5fa7b3cf   Ying Xue   tipc: introduce n...
263
264
265
266
267
268
269
270
  {
  	struct sock *sk = sock->sk;
  	int ret;
  
  	ret = sock_create_lite(sk->sk_family, sk->sk_type,
  			       sk->sk_protocol, newsock);
  	if (ret < 0)
  		return ret;
247f0f3c3   Ying Xue   tipc: align tipc ...
271
  	ret = tipc_accept(sock, *newsock, flags);
c5fa7b3cf   Ying Xue   tipc: introduce n...
272
273
274
275
276
277
278
279
280
  	if (ret < 0) {
  		sock_release(*newsock);
  		return ret;
  	}
  	(*newsock)->ops = sock->ops;
  	return ret;
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
281
   * tipc_release - destroy a TIPC socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
282
283
284
285
286
287
288
   * @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...
289
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
290
291
292
293
294
295
   * 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 ...
296
  static int tipc_release(struct socket *sock)
b97bf3fd8   Per Liden   [TIPC] Initial merge
297
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
298
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
299
300
  	struct tipc_sock *tsk;
  	struct tipc_port *port;
b97bf3fd8   Per Liden   [TIPC] Initial merge
301
  	struct sk_buff *buf;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
302
  	u32 dnode;
b97bf3fd8   Per Liden   [TIPC] Initial merge
303

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
304
305
306
307
  	/*
  	 * 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 ...
308
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
309
  		return 0;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
310

58ed94424   Jon Paul Maloy   tipc: align usage...
311
312
  	tsk = tipc_sk(sk);
  	port = &tsk->port;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
313
314
315
316
317
318
  	lock_sock(sk);
  
  	/*
  	 * Reject all unreceived messages, except on an active connection
  	 * (which disconnects locally & sends a 'FIN+' to peer)
  	 */
b97bf3fd8   Per Liden   [TIPC] Initial merge
319
  	while (sock->state != SS_DISCONNECTING) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
320
321
  		buf = __skb_dequeue(&sk->sk_receive_queue);
  		if (buf == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
322
  			break;
406824320   Ying Xue   tipc: silence spa...
323
  		if (TIPC_SKB_CB(buf)->handle != NULL)
5f6d9123f   Allan Stephens   tipc: Eliminate t...
324
  			kfree_skb(buf);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
325
326
327
328
  		else {
  			if ((sock->state == SS_CONNECTING) ||
  			    (sock->state == SS_CONNECTED)) {
  				sock->state = SS_DISCONNECTING;
58ed94424   Jon Paul Maloy   tipc: align usage...
329
  				tipc_port_disconnect(port->ref);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
330
  			}
8db1bae30   Jon Paul Maloy   tipc: separate bu...
331
332
  			if (tipc_msg_reverse(buf, &dnode, TIPC_ERR_NO_PORT))
  				tipc_link_xmit2(buf, dnode, 0);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
333
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
334
  	}
58ed94424   Jon Paul Maloy   tipc: align usage...
335
336
  	/* Destroy TIPC port; also disconnects an active connection and
  	 * sends a 'FIN-' to peer.
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
337
  	 */
58ed94424   Jon Paul Maloy   tipc: align usage...
338
  	tipc_port_destroy(port);
b97bf3fd8   Per Liden   [TIPC] Initial merge
339

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
340
  	/* Discard any remaining (connection-based) messages in receive queue */
57467e562   Ying Xue   tipc: eliminate d...
341
  	__skb_queue_purge(&sk->sk_receive_queue);
b97bf3fd8   Per Liden   [TIPC] Initial merge
342

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
343
  	/* Reject any messages that accumulated in backlog queue */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
344
345
  	sock->state = SS_DISCONNECTING;
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
346
347
  
  	sock_put(sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
348
  	sock->sk = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
349

065d7e395   Geert Uytterhoeven   tipc: Let tipc_re...
350
  	return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
351
352
353
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
354
   * tipc_bind - associate or disassocate TIPC name(s) with a socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
355
356
357
   * @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...
358
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
359
360
361
   * 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...
362
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
363
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
364
365
366
   *
   * 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
367
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
368
369
  static int tipc_bind(struct socket *sock, struct sockaddr *uaddr,
  		     int uaddr_len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
370
  {
84602761c   Ying Xue   tipc: fix deadloc...
371
  	struct sock *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
372
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
58ed94424   Jon Paul Maloy   tipc: align usage...
373
  	struct tipc_sock *tsk = tipc_sk(sk);
84602761c   Ying Xue   tipc: fix deadloc...
374
  	int res = -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
375

84602761c   Ying Xue   tipc: fix deadloc...
376
377
  	lock_sock(sk);
  	if (unlikely(!uaddr_len)) {
58ed94424   Jon Paul Maloy   tipc: align usage...
378
  		res = tipc_withdraw(&tsk->port, 0, NULL);
84602761c   Ying Xue   tipc: fix deadloc...
379
380
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
381

84602761c   Ying Xue   tipc: fix deadloc...
382
383
384
385
386
387
388
389
  	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
390

b97bf3fd8   Per Liden   [TIPC] Initial merge
391
392
  	if (addr->addrtype == TIPC_ADDR_NAME)
  		addr->addr.nameseq.upper = addr->addr.nameseq.lower;
84602761c   Ying Xue   tipc: fix deadloc...
393
394
395
396
  	else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
  		res = -EAFNOSUPPORT;
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
397

13a2e8987   Ying Xue   tipc: convert top...
398
  	if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) &&
7d0ab17b7   Ying Xue   tipc: convert con...
399
  	    (addr->addr.nameseq.type != TIPC_TOP_SRV) &&
84602761c   Ying Xue   tipc: fix deadloc...
400
401
402
403
  	    (addr->addr.nameseq.type != TIPC_CFG_SRV)) {
  		res = -EACCES;
  		goto exit;
  	}
c422f1bdc   Allan Stephens   tipc: Simplify en...
404

84602761c   Ying Xue   tipc: fix deadloc...
405
  	res = (addr->scope > 0) ?
58ed94424   Jon Paul Maloy   tipc: align usage...
406
407
  		tipc_publish(&tsk->port, addr->scope, &addr->addr.nameseq) :
  		tipc_withdraw(&tsk->port, -addr->scope, &addr->addr.nameseq);
84602761c   Ying Xue   tipc: fix deadloc...
408
409
410
  exit:
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
411
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
412
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
413
   * tipc_getname - get port ID of socket or peer socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
414
415
416
   * @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...
417
   * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
418
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
419
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
420
   *
2da59918e   Allan Stephens   tipc: Fix race co...
421
422
   * 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...
423
   *       a completely predictable manner).
b97bf3fd8   Per Liden   [TIPC] Initial merge
424
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
425
426
  static int tipc_getname(struct socket *sock, struct sockaddr *uaddr,
  			int *uaddr_len, int peer)
b97bf3fd8   Per Liden   [TIPC] Initial merge
427
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
428
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
58ed94424   Jon Paul Maloy   tipc: align usage...
429
  	struct tipc_sock *tsk = tipc_sk(sock->sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
430

88f8a5e3e   Kulikov Vasiliy   net: tipc: fix in...
431
  	memset(addr, 0, sizeof(*addr));
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
432
  	if (peer) {
2da59918e   Allan Stephens   tipc: Fix race co...
433
434
435
  		if ((sock->state != SS_CONNECTED) &&
  			((peer != 2) || (sock->state != SS_DISCONNECTING)))
  			return -ENOTCONN;
58ed94424   Jon Paul Maloy   tipc: align usage...
436
437
  		addr->addr.id.ref = tipc_port_peerport(&tsk->port);
  		addr->addr.id.node = tipc_port_peernode(&tsk->port);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
438
  	} else {
58ed94424   Jon Paul Maloy   tipc: align usage...
439
  		addr->addr.id.ref = tsk->port.ref;
b924dcf00   Allan Stephens   tipc: Delete tipc...
440
  		addr->addr.id.node = tipc_own_addr;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
441
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
442
443
444
445
446
  
  	*uaddr_len = sizeof(*addr);
  	addr->addrtype = TIPC_ADDR_ID;
  	addr->family = AF_TIPC;
  	addr->scope = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
447
  	addr->addr.name.domain = 0;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
448
  	return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
449
450
451
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
452
   * tipc_poll - read and possibly block on pollmask
b97bf3fd8   Per Liden   [TIPC] Initial merge
453
454
455
456
   * @file: file structure associated with the socket
   * @sock: socket for which to calculate the poll bits
   * @wait: ???
   *
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
457
458
459
460
461
462
463
464
465
   * Returns pollmask value
   *
   * COMMENTARY:
   * It appears that the usual socket locking mechanisms are not useful here
   * since the pollmask info is potentially out-of-date the moment this routine
   * exits.  TCP and other protocols seem to rely on higher level poll routines
   * to handle any preventable race conditions, so TIPC will do the same ...
   *
   * TIPC sets the returned events as follows:
f662c0705   Allan Stephens   tipc: correct pro...
466
467
468
469
   *
   * socket state		flags set
   * ------------		---------
   * unconnected		no read flags
c4fc298ab   Erik Hugne   tipc: return POLL...
470
   *			POLLOUT if port is not congested
f662c0705   Allan Stephens   tipc: correct pro...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
   *
   * connecting		POLLIN/POLLRDNORM if ACK/NACK in rx queue
   *			no write flags
   *
   * connected		POLLIN/POLLRDNORM if data in rx queue
   *			POLLOUT if port is not congested
   *
   * disconnecting	POLLIN/POLLRDNORM/POLLHUP
   *			no write flags
   *
   * listening		POLLIN if SYN in rx queue
   *			no write flags
   *
   * ready		POLLIN/POLLRDNORM if data in rx queue
   * [connectionless]	POLLOUT (since port cannot be congested)
   *
   * IMPORTANT: The fact that a read or write operation is indicated does NOT
   * imply that the operation will succeed, merely that it should be performed
   * and will not block.
b97bf3fd8   Per Liden   [TIPC] Initial merge
490
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
491
492
  static unsigned int tipc_poll(struct file *file, struct socket *sock,
  			      poll_table *wait)
b97bf3fd8   Per Liden   [TIPC] Initial merge
493
  {
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
494
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
495
  	struct tipc_sock *tsk = tipc_sk(sk);
f662c0705   Allan Stephens   tipc: correct pro...
496
  	u32 mask = 0;
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
497

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

f662c0705   Allan Stephens   tipc: correct pro...
500
  	switch ((int)sock->state) {
c4fc298ab   Erik Hugne   tipc: return POLL...
501
  	case SS_UNCONNECTED:
58ed94424   Jon Paul Maloy   tipc: align usage...
502
  		if (!tsk->port.congested)
c4fc298ab   Erik Hugne   tipc: return POLL...
503
504
  			mask |= POLLOUT;
  		break;
f662c0705   Allan Stephens   tipc: correct pro...
505
506
  	case SS_READY:
  	case SS_CONNECTED:
58ed94424   Jon Paul Maloy   tipc: align usage...
507
  		if (!tsk->port.congested)
f662c0705   Allan Stephens   tipc: correct pro...
508
509
510
511
512
513
514
515
516
517
518
  			mask |= POLLOUT;
  		/* fall thru' */
  	case SS_CONNECTING:
  	case SS_LISTENING:
  		if (!skb_queue_empty(&sk->sk_receive_queue))
  			mask |= (POLLIN | POLLRDNORM);
  		break;
  	case SS_DISCONNECTING:
  		mask = (POLLIN | POLLRDNORM | POLLHUP);
  		break;
  	}
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
519
520
  
  	return mask;
b97bf3fd8   Per Liden   [TIPC] Initial merge
521
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
522
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
523
524
525
   * dest_name_check - verify user is permitted to send to specified port name
   * @dest: destination address
   * @m: descriptor for message to be sent
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
526
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
527
528
   * Prevents restricted configuration commands from being issued by
   * unauthorized users.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
529
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
530
531
   * Returns 0 if permission is granted, otherwise errno
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
532
  static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
b97bf3fd8   Per Liden   [TIPC] Initial merge
533
534
  {
  	struct tipc_cfg_msg_hdr hdr;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
535
536
537
538
  	if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES))
  		return 0;
  	if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
  		return 0;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
539
540
  	if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
  		return -EACCES;
b97bf3fd8   Per Liden   [TIPC] Initial merge
541

3f8dd9446   Allan Stephens   tipc: Prevent inv...
542
543
  	if (!m->msg_iovlen || (m->msg_iov[0].iov_len < sizeof(hdr)))
  		return -EMSGSIZE;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
544
  	if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
b97bf3fd8   Per Liden   [TIPC] Initial merge
545
  		return -EFAULT;
70cb23477   Allan Stephens   [TIPC]: Fixed pri...
546
  	if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN)))
b97bf3fd8   Per Liden   [TIPC] Initial merge
547
  		return -EACCES;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
548

b97bf3fd8   Per Liden   [TIPC] Initial merge
549
550
  	return 0;
  }
3f40504f7   Ying Xue   tipc: standardize...
551
552
553
  static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
  {
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
554
  	struct tipc_sock *tsk = tipc_sk(sk);
3f40504f7   Ying Xue   tipc: standardize...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  	DEFINE_WAIT(wait);
  	int done;
  
  	do {
  		int err = sock_error(sk);
  		if (err)
  			return err;
  		if (sock->state == SS_DISCONNECTING)
  			return -EPIPE;
  		if (!*timeo_p)
  			return -EAGAIN;
  		if (signal_pending(current))
  			return sock_intr_errno(*timeo_p);
  
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
58ed94424   Jon Paul Maloy   tipc: align usage...
570
  		done = sk_wait_event(sk, timeo_p, !tsk->port.congested);
3f40504f7   Ying Xue   tipc: standardize...
571
572
573
574
  		finish_wait(sk_sleep(sk), &wait);
  	} while (!done);
  	return 0;
  }
58ed94424   Jon Paul Maloy   tipc: align usage...
575

b97bf3fd8   Per Liden   [TIPC] Initial merge
576
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
577
   * tipc_sendmsg - send message in connectionless manner
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
578
   * @iocb: if NULL, indicates that socket lock is already held
b97bf3fd8   Per Liden   [TIPC] Initial merge
579
580
   * @sock: socket structure
   * @m: message to send
e9024f0f7   Allan Stephens   [TIPC]: Non-opera...
581
   * @total_len: length of message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
582
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
583
   * Message must have an destination specified explicitly.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
584
   * Used for SOCK_RDM and SOCK_DGRAM messages,
b97bf3fd8   Per Liden   [TIPC] Initial merge
585
586
   * 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...
587
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
588
589
   * Returns the number of bytes sent on success, or errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
590
591
  static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock,
  			struct msghdr *m, size_t total_len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
592
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
593
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
594
  	struct tipc_sock *tsk = tipc_sk(sk);
5c311421a   Jon Paul Maloy   tipc: eliminate r...
595
  	struct tipc_port *port = &tsk->port;
342dfc306   Steffen Hurrle   net: add build-ti...
596
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
b97bf3fd8   Per Liden   [TIPC] Initial merge
597
  	int needs_conn;
3f40504f7   Ying Xue   tipc: standardize...
598
  	long timeo;
b97bf3fd8   Per Liden   [TIPC] Initial merge
599
600
601
602
  	int res = -EINVAL;
  
  	if (unlikely(!dest))
  		return -EDESTADDRREQ;
51f9cc1ff   Allan Stephens   [TIPC]: Optimized...
603
604
  	if (unlikely((m->msg_namelen < sizeof(*dest)) ||
  		     (dest->family != AF_TIPC)))
b97bf3fd8   Per Liden   [TIPC] Initial merge
605
  		return -EINVAL;
97f8b87e9   Ying Xue   tipc: remove redu...
606
  	if (total_len > TIPC_MAX_USER_MSG_SIZE)
c29c3f70c   Allan Stephens   tipc: Abort exces...
607
  		return -EMSGSIZE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
608

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
609
610
  	if (iocb)
  		lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
611
612
  	needs_conn = (sock->state != SS_READY);
  	if (unlikely(needs_conn)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
613
614
615
616
617
618
619
620
  		if (sock->state == SS_LISTENING) {
  			res = -EPIPE;
  			goto exit;
  		}
  		if (sock->state != SS_UNCONNECTED) {
  			res = -EISCONN;
  			goto exit;
  		}
58ed94424   Jon Paul Maloy   tipc: align usage...
621
  		if (tsk->port.published) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
622
623
624
  			res = -EOPNOTSUPP;
  			goto exit;
  		}
3388007bc   Allan Stephens   [TIPC]: Implied c...
625
  		if (dest->addrtype == TIPC_ADDR_NAME) {
58ed94424   Jon Paul Maloy   tipc: align usage...
626
627
  			tsk->port.conn_type = dest->addr.name.name.type;
  			tsk->port.conn_instance = dest->addr.name.name.instance;
3388007bc   Allan Stephens   [TIPC]: Implied c...
628
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
629
630
  
  		/* Abort any pending connection attempts (very unlikely) */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
631
  		reject_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
632
  	}
3f40504f7   Ying Xue   tipc: standardize...
633
  	timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
634
635
  	do {
  		if (dest->addrtype == TIPC_ADDR_NAME) {
2db9983a4   Allan Stephens   tipc: split varia...
636
637
  			res = dest_name_check(dest, m);
  			if (res)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
638
  				break;
5c311421a   Jon Paul Maloy   tipc: eliminate r...
639
  			res = tipc_send2name(port,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
640
641
  					     &dest->addr.name.name,
  					     dest->addr.name.domain,
268969046   Allan Stephens   tipc: Avoid recom...
642
643
  					     m->msg_iov,
  					     total_len);
0e65967e3   Allan Stephens   tipc: cleanup var...
644
  		} else if (dest->addrtype == TIPC_ADDR_ID) {
5c311421a   Jon Paul Maloy   tipc: eliminate r...
645
  			res = tipc_send2port(port,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
646
  					     &dest->addr.id,
268969046   Allan Stephens   tipc: Avoid recom...
647
648
  					     m->msg_iov,
  					     total_len);
0e65967e3   Allan Stephens   tipc: cleanup var...
649
  		} else if (dest->addrtype == TIPC_ADDR_MCAST) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
650
651
  			if (needs_conn) {
  				res = -EOPNOTSUPP;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
652
  				break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
653
  			}
2db9983a4   Allan Stephens   tipc: split varia...
654
655
  			res = dest_name_check(dest, m);
  			if (res)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
656
  				break;
5c311421a   Jon Paul Maloy   tipc: eliminate r...
657
  			res = tipc_port_mcast_xmit(port,
247f0f3c3   Ying Xue   tipc: align tipc ...
658
659
660
  						   &dest->addr.nameseq,
  						   m->msg_iov,
  						   total_len);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
661
662
  		}
  		if (likely(res != -ELINKCONG)) {
a016892cd   Allan Stephens   tipc: remove extr...
663
  			if (needs_conn && (res >= 0))
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
664
  				sock->state = SS_CONNECTING;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
665
  			break;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
666
  		}
3f40504f7   Ying Xue   tipc: standardize...
667
668
  		res = tipc_wait_for_sndmsg(sock, &timeo);
  		if (res)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
669
  			break;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
670
  	} while (1);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
671
672
673
674
675
  
  exit:
  	if (iocb)
  		release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
676
  }
391a6dd1d   Ying Xue   tipc: standardize...
677
678
679
  static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p)
  {
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
680
681
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_port *port = &tsk->port;
391a6dd1d   Ying Xue   tipc: standardize...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  	DEFINE_WAIT(wait);
  	int done;
  
  	do {
  		int err = sock_error(sk);
  		if (err)
  			return err;
  		if (sock->state == SS_DISCONNECTING)
  			return -EPIPE;
  		else if (sock->state != SS_CONNECTED)
  			return -ENOTCONN;
  		if (!*timeo_p)
  			return -EAGAIN;
  		if (signal_pending(current))
  			return sock_intr_errno(*timeo_p);
  
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  		done = sk_wait_event(sk, timeo_p,
58ed94424   Jon Paul Maloy   tipc: align usage...
700
  				     (!port->congested || !port->connected));
391a6dd1d   Ying Xue   tipc: standardize...
701
702
703
704
  		finish_wait(sk_sleep(sk), &wait);
  	} while (!done);
  	return 0;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
705
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
706
   * tipc_send_packet - send a connection-oriented message
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
707
   * @iocb: if NULL, indicates that socket lock is already held
b97bf3fd8   Per Liden   [TIPC] Initial merge
708
709
   * @sock: socket structure
   * @m: message to send
e9024f0f7   Allan Stephens   [TIPC]: Non-opera...
710
   * @total_len: length of message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
711
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
712
   * Used for SOCK_SEQPACKET messages and SOCK_STREAM data.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
713
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
714
715
   * Returns the number of bytes sent on success, or errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
716
717
  static int tipc_send_packet(struct kiocb *iocb, struct socket *sock,
  			    struct msghdr *m, size_t total_len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
718
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
719
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
720
  	struct tipc_sock *tsk = tipc_sk(sk);
342dfc306   Steffen Hurrle   net: add build-ti...
721
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
391a6dd1d   Ying Xue   tipc: standardize...
722
723
  	int res = -EINVAL;
  	long timeo;
b97bf3fd8   Per Liden   [TIPC] Initial merge
724
725
  
  	/* Handle implied connection establishment */
b97bf3fd8   Per Liden   [TIPC] Initial merge
726
  	if (unlikely(dest))
247f0f3c3   Ying Xue   tipc: align tipc ...
727
  		return tipc_sendmsg(iocb, sock, m, total_len);
b97bf3fd8   Per Liden   [TIPC] Initial merge
728

97f8b87e9   Ying Xue   tipc: remove redu...
729
  	if (total_len > TIPC_MAX_USER_MSG_SIZE)
c29c3f70c   Allan Stephens   tipc: Abort exces...
730
  		return -EMSGSIZE;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
731
732
  	if (iocb)
  		lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
733

391a6dd1d   Ying Xue   tipc: standardize...
734
735
736
737
738
739
740
  	if (unlikely(sock->state != SS_CONNECTED)) {
  		if (sock->state == SS_DISCONNECTING)
  			res = -EPIPE;
  		else
  			res = -ENOTCONN;
  		goto exit;
  	}
1d835874a   Ying Xue   tipc: Add support...
741

391a6dd1d   Ying Xue   tipc: standardize...
742
  	timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
743
  	do {
5c311421a   Jon Paul Maloy   tipc: eliminate r...
744
  		res = tipc_send(&tsk->port, m->msg_iov, total_len);
a016892cd   Allan Stephens   tipc: remove extr...
745
  		if (likely(res != -ELINKCONG))
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
746
  			break;
391a6dd1d   Ying Xue   tipc: standardize...
747
748
  		res = tipc_wait_for_sndpkt(sock, &timeo);
  		if (res)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
749
  			break;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
750
  	} while (1);
391a6dd1d   Ying Xue   tipc: standardize...
751
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
752
753
754
  	if (iocb)
  		release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
755
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
756
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
757
   * tipc_send_stream - send stream-oriented data
b97bf3fd8   Per Liden   [TIPC] Initial merge
758
759
760
761
   * @iocb: (unused)
   * @sock: socket structure
   * @m: data to send
   * @total_len: total length of data to be sent
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
762
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
763
   * Used for SOCK_STREAM data.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
764
765
   *
   * Returns the number of bytes sent on success (or partial success),
1303e8f17   Allan Stephens   [TIPC]: Stream so...
766
   * or errno if no data sent
b97bf3fd8   Per Liden   [TIPC] Initial merge
767
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
768
769
  static int tipc_send_stream(struct kiocb *iocb, struct socket *sock,
  			    struct msghdr *m, size_t total_len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
770
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
771
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
772
  	struct tipc_sock *tsk = tipc_sk(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
773
774
775
776
777
  	struct msghdr my_msg;
  	struct iovec my_iov;
  	struct iovec *curr_iov;
  	int curr_iovlen;
  	char __user *curr_start;
05646c911   Allan Stephens   [TIPC]: Optimize ...
778
  	u32 hdr_size;
b97bf3fd8   Per Liden   [TIPC] Initial merge
779
780
  	int curr_left;
  	int bytes_to_send;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
781
  	int bytes_sent;
b97bf3fd8   Per Liden   [TIPC] Initial merge
782
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
783

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
784
  	lock_sock(sk);
05646c911   Allan Stephens   [TIPC]: Optimize ...
785
  	/* Handle special cases where there is no connection */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
786
  	if (unlikely(sock->state != SS_CONNECTED)) {
3b8401fe9   wangweidong   tipc: kill unnece...
787
  		if (sock->state == SS_UNCONNECTED)
247f0f3c3   Ying Xue   tipc: align tipc ...
788
  			res = tipc_send_packet(NULL, sock, m, total_len);
b05559769   wangweidong   tipc: make the co...
789
790
  		else
  			res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN;
3b8401fe9   wangweidong   tipc: kill unnece...
791
  		goto exit;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
792
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
793

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
794
795
796
797
  	if (unlikely(m->msg_name)) {
  		res = -EISCONN;
  		goto exit;
  	}
eb5959c2b   Allan Stephens   [TIPC]: Stream so...
798

97f8b87e9   Ying Xue   tipc: remove redu...
799
  	if (total_len > (unsigned int)INT_MAX) {
c29c3f70c   Allan Stephens   tipc: Abort exces...
800
801
802
  		res = -EMSGSIZE;
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
803
  	/*
b97bf3fd8   Per Liden   [TIPC] Initial merge
804
805
  	 * Send each iovec entry using one or more messages
  	 *
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
806
  	 * Note: This algorithm is good for the most likely case
b97bf3fd8   Per Liden   [TIPC] Initial merge
807
808
809
  	 * (i.e. one large iovec entry), but could be improved to pass sets
  	 * of small iovec entries into send_packet().
  	 */
1303e8f17   Allan Stephens   [TIPC]: Stream so...
810
811
  	curr_iov = m->msg_iov;
  	curr_iovlen = m->msg_iovlen;
b97bf3fd8   Per Liden   [TIPC] Initial merge
812
813
  	my_msg.msg_iov = &my_iov;
  	my_msg.msg_iovlen = 1;
eb5959c2b   Allan Stephens   [TIPC]: Stream so...
814
815
  	my_msg.msg_flags = m->msg_flags;
  	my_msg.msg_name = NULL;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
816
  	bytes_sent = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
817

58ed94424   Jon Paul Maloy   tipc: align usage...
818
  	hdr_size = msg_hdr_sz(&tsk->port.phdr);
05646c911   Allan Stephens   [TIPC]: Optimize ...
819

b97bf3fd8   Per Liden   [TIPC] Initial merge
820
821
822
823
824
  	while (curr_iovlen--) {
  		curr_start = curr_iov->iov_base;
  		curr_left = curr_iov->iov_len;
  
  		while (curr_left) {
58ed94424   Jon Paul Maloy   tipc: align usage...
825
  			bytes_to_send = tsk->port.max_pkt - hdr_size;
05646c911   Allan Stephens   [TIPC]: Optimize ...
826
827
828
829
  			if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE)
  				bytes_to_send = TIPC_MAX_USER_MSG_SIZE;
  			if (curr_left < bytes_to_send)
  				bytes_to_send = curr_left;
b97bf3fd8   Per Liden   [TIPC] Initial merge
830
831
  			my_iov.iov_base = curr_start;
  			my_iov.iov_len = bytes_to_send;
247f0f3c3   Ying Xue   tipc: align tipc ...
832
833
  			res = tipc_send_packet(NULL, sock, &my_msg,
  					       bytes_to_send);
2db9983a4   Allan Stephens   tipc: split varia...
834
  			if (res < 0) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
835
  				if (bytes_sent)
05646c911   Allan Stephens   [TIPC]: Optimize ...
836
  					res = bytes_sent;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
837
  				goto exit;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
838
  			}
b97bf3fd8   Per Liden   [TIPC] Initial merge
839
840
  			curr_left -= bytes_to_send;
  			curr_start += bytes_to_send;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
841
  			bytes_sent += bytes_to_send;
b97bf3fd8   Per Liden   [TIPC] Initial merge
842
843
844
845
  		}
  
  		curr_iov++;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
846
847
848
849
  	res = bytes_sent;
  exit:
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
850
851
852
853
  }
  
  /**
   * auto_connect - complete connection setup to a remote port
58ed94424   Jon Paul Maloy   tipc: align usage...
854
   * @tsk: tipc socket structure
b97bf3fd8   Per Liden   [TIPC] Initial merge
855
   * @msg: peer's response message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
856
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
857
858
   * Returns 0 on success, errno otherwise
   */
58ed94424   Jon Paul Maloy   tipc: align usage...
859
  static int auto_connect(struct tipc_sock *tsk, struct tipc_msg *msg)
b97bf3fd8   Per Liden   [TIPC] Initial merge
860
  {
58ed94424   Jon Paul Maloy   tipc: align usage...
861
862
  	struct tipc_port *port = &tsk->port;
  	struct socket *sock = tsk->sk.sk_socket;
f9fef18c6   Jon Paul Maloy   tipc: remove redu...
863
864
865
866
  	struct tipc_portid peer;
  
  	peer.ref = msg_origport(msg);
  	peer.node = msg_orignode(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
867

58ed94424   Jon Paul Maloy   tipc: align usage...
868
  	__tipc_port_connect(port->ref, port, &peer);
584d24b39   Ying Xue   tipc: introduce n...
869
870
871
  
  	if (msg_importance(msg) > TIPC_CRITICAL_IMPORTANCE)
  		return -EINVAL;
58ed94424   Jon Paul Maloy   tipc: align usage...
872
  	msg_set_importance(&port->phdr, (u32)msg_importance(msg));
b97bf3fd8   Per Liden   [TIPC] Initial merge
873
874
875
876
877
878
879
880
  	sock->state = SS_CONNECTED;
  	return 0;
  }
  
  /**
   * 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...
881
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
882
883
   * Note: Address is not captured if not requested by receiver.
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
884
  static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
b97bf3fd8   Per Liden   [TIPC] Initial merge
885
  {
342dfc306   Steffen Hurrle   net: add build-ti...
886
  	DECLARE_SOCKADDR(struct sockaddr_tipc *, addr, m->msg_name);
b97bf3fd8   Per Liden   [TIPC] Initial merge
887

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
888
  	if (addr) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
889
890
  		addr->family = AF_TIPC;
  		addr->addrtype = TIPC_ADDR_ID;
60085c3d0   Mathias Krause   tipc: fix info le...
891
  		memset(&addr->addr, 0, sizeof(addr->addr));
b97bf3fd8   Per Liden   [TIPC] Initial merge
892
893
  		addr->addr.id.ref = msg_origport(msg);
  		addr->addr.id.node = msg_orignode(msg);
0e65967e3   Allan Stephens   tipc: cleanup var...
894
895
  		addr->addr.name.domain = 0;	/* could leave uninitialized */
  		addr->scope = 0;		/* could leave uninitialized */
b97bf3fd8   Per Liden   [TIPC] Initial merge
896
897
898
899
900
  		m->msg_namelen = sizeof(struct sockaddr_tipc);
  	}
  }
  
  /**
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
901
   * anc_data_recv - optionally capture ancillary data for received message
b97bf3fd8   Per Liden   [TIPC] Initial merge
902
903
904
   * @m: descriptor for message info
   * @msg: received message header
   * @tport: TIPC port associated with message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
905
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
906
   * Note: Ancillary data is not captured if not requested by receiver.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
907
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
908
909
   * Returns 0 if successful, otherwise errno
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
910
  static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
ae8509c42   Paul Gortmaker   tipc: cosmetic re...
911
  			 struct tipc_port *tport)
b97bf3fd8   Per Liden   [TIPC] Initial merge
912
913
914
915
  {
  	u32 anc_data[3];
  	u32 err;
  	u32 dest_type;
3546c7508   Allan Stephens   [TIPC]: Can now r...
916
  	int has_name;
b97bf3fd8   Per Liden   [TIPC] Initial merge
917
918
919
920
921
922
  	int res;
  
  	if (likely(m->msg_controllen == 0))
  		return 0;
  
  	/* Optionally capture errored message object(s) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
923
924
925
926
  	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...
927
928
  		res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
929
  			return res;
2db9983a4   Allan Stephens   tipc: split varia...
930
931
932
933
934
935
  		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
936
937
938
  	}
  
  	/* Optionally capture message destination object */
b97bf3fd8   Per Liden   [TIPC] Initial merge
939
940
941
  	dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
  	switch (dest_type) {
  	case TIPC_NAMED_MSG:
3546c7508   Allan Stephens   [TIPC]: Can now r...
942
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
943
944
945
946
947
  		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...
948
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
949
950
951
952
953
  		anc_data[0] = msg_nametype(msg);
  		anc_data[1] = msg_namelower(msg);
  		anc_data[2] = msg_nameupper(msg);
  		break;
  	case TIPC_CONN_MSG:
3546c7508   Allan Stephens   [TIPC]: Can now r...
954
  		has_name = (tport->conn_type != 0);
b97bf3fd8   Per Liden   [TIPC] Initial merge
955
956
957
958
959
  		anc_data[0] = tport->conn_type;
  		anc_data[1] = tport->conn_instance;
  		anc_data[2] = tport->conn_instance;
  		break;
  	default:
3546c7508   Allan Stephens   [TIPC]: Can now r...
960
  		has_name = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
961
  	}
2db9983a4   Allan Stephens   tipc: split varia...
962
963
964
965
966
  	if (has_name) {
  		res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data);
  		if (res)
  			return res;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
967
968
969
  
  	return 0;
  }
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
970
  static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
9bbb4ecc6   Ying Xue   tipc: standardize...
971
972
973
  {
  	struct sock *sk = sock->sk;
  	DEFINE_WAIT(wait);
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
974
  	long timeo = *timeop;
9bbb4ecc6   Ying Xue   tipc: standardize...
975
976
977
978
  	int err;
  
  	for (;;) {
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
fe8e46493   Ying Xue   tipc: avoid to un...
979
  		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
9bbb4ecc6   Ying Xue   tipc: standardize...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
  			if (sock->state == SS_DISCONNECTING) {
  				err = -ENOTCONN;
  				break;
  			}
  			release_sock(sk);
  			timeo = schedule_timeout(timeo);
  			lock_sock(sk);
  		}
  		err = 0;
  		if (!skb_queue_empty(&sk->sk_receive_queue))
  			break;
  		err = sock_intr_errno(timeo);
  		if (signal_pending(current))
  			break;
  		err = -EAGAIN;
  		if (!timeo)
  			break;
  	}
  	finish_wait(sk_sleep(sk), &wait);
85d3fc941   Arnaldo Carvalho de Melo   tipc: Don't reset...
999
  	*timeop = timeo;
9bbb4ecc6   Ying Xue   tipc: standardize...
1000
1001
  	return err;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1002
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1003
   * tipc_recvmsg - receive packet-oriented message
b97bf3fd8   Per Liden   [TIPC] Initial merge
1004
1005
1006
1007
   * @iocb: (unused)
   * @m: descriptor for message info
   * @buf_len: total size of user buffer area
   * @flags: receive flags
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1008
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1009
1010
1011
1012
1013
   * 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
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1014
1015
  static int tipc_recvmsg(struct kiocb *iocb, struct socket *sock,
  			struct msghdr *m, size_t buf_len, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1016
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1017
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1018
1019
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_port *port = &tsk->port;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1020
1021
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
9bbb4ecc6   Ying Xue   tipc: standardize...
1022
  	long timeo;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1023
1024
1025
  	unsigned int sz;
  	u32 err;
  	int res;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1026
  	/* Catch invalid receive requests */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1027
1028
  	if (unlikely(!buf_len))
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1029
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1030

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1031
1032
  	if (unlikely(sock->state == SS_UNCONNECTED)) {
  		res = -ENOTCONN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1033
1034
  		goto exit;
  	}
9bbb4ecc6   Ying Xue   tipc: standardize...
1035
  	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1036
  restart:
b97bf3fd8   Per Liden   [TIPC] Initial merge
1037

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

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1043
  	/* Look at first message in receive queue */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1044
  	buf = skb_peek(&sk->sk_receive_queue);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1045
1046
1047
  	msg = buf_msg(buf);
  	sz = msg_data_sz(msg);
  	err = msg_errcode(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1048
  	/* Discard an empty non-errored message & try again */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1049
  	if ((!sz) && (!err)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1050
  		advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1051
1052
1053
1054
  		goto restart;
  	}
  
  	/* Capture sender's address (optional) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1055
1056
1057
  	set_orig_addr(m, msg);
  
  	/* Capture ancillary data (optional) */
58ed94424   Jon Paul Maloy   tipc: align usage...
1058
  	res = anc_data_recv(m, msg, port);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1059
  	if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1060
1061
1062
  		goto exit;
  
  	/* Capture message data (if valid) & compute return value (always) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1063
1064
1065
1066
1067
  	if (!err) {
  		if (unlikely(buf_len < sz)) {
  			sz = buf_len;
  			m->msg_flags |= MSG_TRUNC;
  		}
0232fd0ac   Allan Stephens   tipc: Allow recei...
1068
1069
1070
  		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
  					      m->msg_iov, sz);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1071
  			goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
  		res = sz;
  	} else {
  		if ((sock->state == SS_READY) ||
  		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
  			res = 0;
  		else
  			res = -ECONNRESET;
  	}
  
  	/* Consume received message (optional) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1082
  	if (likely(!(flags & MSG_PEEK))) {
990098068   Allan Stephens   [TIPC]: Skip conn...
1083
  		if ((sock->state != SS_READY) &&
6163a194e   Jon Paul Maloy   tipc: decrease co...
1084
  		    (++port->conn_unacked >= TIPC_CONNACK_INTV))
58ed94424   Jon Paul Maloy   tipc: align usage...
1085
  			tipc_acknowledge(port->ref, port->conn_unacked);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1086
  		advance_rx_queue(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1087
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1088
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1089
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1090
1091
  	return res;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1092
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1093
   * tipc_recv_stream - receive stream-oriented data
b97bf3fd8   Per Liden   [TIPC] Initial merge
1094
1095
1096
1097
   * @iocb: (unused)
   * @m: descriptor for message info
   * @buf_len: total size of user buffer area
   * @flags: receive flags
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1098
1099
   *
   * Used for SOCK_STREAM messages only.  If not enough data is available
b97bf3fd8   Per Liden   [TIPC] Initial merge
1100
1101
1102
1103
   * will optionally wait for more; never truncates data.
   *
   * Returns size of returned message data, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1104
1105
  static int tipc_recv_stream(struct kiocb *iocb, struct socket *sock,
  			    struct msghdr *m, size_t buf_len, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1106
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1107
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1108
1109
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_port *port = &tsk->port;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1110
1111
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
9bbb4ecc6   Ying Xue   tipc: standardize...
1112
  	long timeo;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1113
  	unsigned int sz;
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1114
  	int sz_to_copy, target, needed;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1115
  	int sz_copied = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1116
  	u32 err;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1117
  	int res = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1118

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1119
  	/* Catch invalid receive attempts */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1120
1121
  	if (unlikely(!buf_len))
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1122
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1123

9bbb4ecc6   Ying Xue   tipc: standardize...
1124
  	if (unlikely(sock->state == SS_UNCONNECTED)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1125
  		res = -ENOTCONN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1126
1127
  		goto exit;
  	}
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1128
  	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
9bbb4ecc6   Ying Xue   tipc: standardize...
1129
  	timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1130

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

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1137
  	/* Look at first message in receive queue */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1138
  	buf = skb_peek(&sk->sk_receive_queue);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1139
1140
1141
1142
1143
  	msg = buf_msg(buf);
  	sz = msg_data_sz(msg);
  	err = msg_errcode(msg);
  
  	/* Discard an empty non-errored message & try again */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1144
  	if ((!sz) && (!err)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1145
  		advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1146
1147
1148
1149
  		goto restart;
  	}
  
  	/* Optionally capture sender's address & ancillary data of first msg */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1150
1151
  	if (sz_copied == 0) {
  		set_orig_addr(m, msg);
58ed94424   Jon Paul Maloy   tipc: align usage...
1152
  		res = anc_data_recv(m, msg, port);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1153
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1154
1155
1156
1157
  			goto exit;
  	}
  
  	/* Capture message data (if valid) & compute return value (always) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1158
  	if (!err) {
0232fd0ac   Allan Stephens   tipc: Allow recei...
1159
  		u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1160

0232fd0ac   Allan Stephens   tipc: Allow recei...
1161
  		sz -= offset;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1162
1163
  		needed = (buf_len - sz_copied);
  		sz_to_copy = (sz <= needed) ? sz : needed;
0232fd0ac   Allan Stephens   tipc: Allow recei...
1164
1165
1166
1167
  
  		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
  					      m->msg_iov, sz_to_copy);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1168
  			goto exit;
0232fd0ac   Allan Stephens   tipc: Allow recei...
1169

b97bf3fd8   Per Liden   [TIPC] Initial merge
1170
1171
1172
1173
  		sz_copied += sz_to_copy;
  
  		if (sz_to_copy < sz) {
  			if (!(flags & MSG_PEEK))
0232fd0ac   Allan Stephens   tipc: Allow recei...
1174
1175
  				TIPC_SKB_CB(buf)->handle =
  				(void *)(unsigned long)(offset + sz_to_copy);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1176
1177
  			goto exit;
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
  	} else {
  		if (sz_copied != 0)
  			goto exit; /* can't add error msg to valid data */
  
  		if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)
  			res = 0;
  		else
  			res = -ECONNRESET;
  	}
  
  	/* Consume received message (optional) */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1189
  	if (likely(!(flags & MSG_PEEK))) {
6163a194e   Jon Paul Maloy   tipc: decrease co...
1190
  		if (unlikely(++port->conn_unacked >= TIPC_CONNACK_INTV))
58ed94424   Jon Paul Maloy   tipc: align usage...
1191
  			tipc_acknowledge(port->ref, port->conn_unacked);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1192
  		advance_rx_queue(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1193
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1194
1195
  
  	/* Loop around if more data is required */
f64f9e719   Joe Perches   net: Move && and ...
1196
1197
  	if ((sz_copied < buf_len) &&	/* didn't get all requested data */
  	    (!skb_queue_empty(&sk->sk_receive_queue) ||
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1198
  	    (sz_copied < target)) &&	/* and more is ready or required */
f64f9e719   Joe Perches   net: Move && and ...
1199
1200
  	    (!(flags & MSG_PEEK)) &&	/* and aren't just peeking at data */
  	    (!err))			/* and haven't reached a FIN */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1201
1202
1203
  		goto restart;
  
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1204
  	release_sock(sk);
a3b0a5a9d   Allan Stephens   [TIPC]: Simplify ...
1205
  	return sz_copied ? sz_copied : res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1206
1207
1208
  }
  
  /**
f288bef46   Ying Xue   tipc: fix race/in...
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
   * 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);
  	if (wq_has_sleeper(wq))
  		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...
1229
  static void tipc_data_ready(struct sock *sk)
f288bef46   Ying Xue   tipc: fix race/in...
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
  {
  	struct socket_wq *wq;
  
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
  	if (wq_has_sleeper(wq))
  		wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
  						POLLRDNORM | POLLRDBAND);
  	rcu_read_unlock();
  }
  
  /**
7e6c131e1   Ying Xue   tipc: consolidate...
1242
   * filter_connect - Handle all incoming messages for a connection-based socket
58ed94424   Jon Paul Maloy   tipc: align usage...
1243
   * @tsk: TIPC socket
7e6c131e1   Ying Xue   tipc: consolidate...
1244
1245
   * @msg: message
   *
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1246
   * Returns 0 (TIPC_OK) if everyting ok, -TIPC_ERR_NO_PORT otherwise
7e6c131e1   Ying Xue   tipc: consolidate...
1247
   */
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1248
  static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf)
7e6c131e1   Ying Xue   tipc: consolidate...
1249
  {
58ed94424   Jon Paul Maloy   tipc: align usage...
1250
1251
  	struct sock *sk = &tsk->sk;
  	struct tipc_port *port = &tsk->port;
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1252
  	struct socket *sock = sk->sk_socket;
7e6c131e1   Ying Xue   tipc: consolidate...
1253
  	struct tipc_msg *msg = buf_msg(*buf);
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1254

e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1255
  	int retval = -TIPC_ERR_NO_PORT;
584d24b39   Ying Xue   tipc: introduce n...
1256
  	int res;
7e6c131e1   Ying Xue   tipc: consolidate...
1257
1258
1259
1260
1261
1262
1263
  
  	if (msg_mcast(msg))
  		return retval;
  
  	switch ((int)sock->state) {
  	case SS_CONNECTED:
  		/* Accept only connection-based messages sent by peer */
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1264
  		if (msg_connected(msg) && tipc_port_peer_msg(port, msg)) {
7e6c131e1   Ying Xue   tipc: consolidate...
1265
1266
  			if (unlikely(msg_errcode(msg))) {
  				sock->state = SS_DISCONNECTING;
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1267
  				__tipc_port_disconnect(port);
7e6c131e1   Ying Xue   tipc: consolidate...
1268
1269
1270
1271
1272
1273
  			}
  			retval = TIPC_OK;
  		}
  		break;
  	case SS_CONNECTING:
  		/* Accept only ACK or NACK message */
584d24b39   Ying Xue   tipc: introduce n...
1274
1275
  		if (unlikely(msg_errcode(msg))) {
  			sock->state = SS_DISCONNECTING;
2c8d85182   Erik Hugne   tipc: set sk_err ...
1276
  			sk->sk_err = ECONNREFUSED;
584d24b39   Ying Xue   tipc: introduce n...
1277
1278
1279
1280
1281
1282
  			retval = TIPC_OK;
  			break;
  		}
  
  		if (unlikely(!msg_connected(msg)))
  			break;
58ed94424   Jon Paul Maloy   tipc: align usage...
1283
  		res = auto_connect(tsk, msg);
584d24b39   Ying Xue   tipc: introduce n...
1284
1285
  		if (res) {
  			sock->state = SS_DISCONNECTING;
2c8d85182   Erik Hugne   tipc: set sk_err ...
1286
  			sk->sk_err = -res;
7e6c131e1   Ying Xue   tipc: consolidate...
1287
  			retval = TIPC_OK;
584d24b39   Ying Xue   tipc: introduce n...
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
  			break;
  		}
  
  		/* If an incoming message is an 'ACK-', it should be
  		 * discarded here because it doesn't contain useful
  		 * data. In addition, we should try to wake up
  		 * connect() routine if sleeping.
  		 */
  		if (msg_data_sz(msg) == 0) {
  			kfree_skb(*buf);
  			*buf = NULL;
  			if (waitqueue_active(sk_sleep(sk)))
  				wake_up_interruptible(sk_sleep(sk));
  		}
  		retval = TIPC_OK;
7e6c131e1   Ying Xue   tipc: consolidate...
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  		break;
  	case SS_LISTENING:
  	case SS_UNCONNECTED:
  		/* Accept only SYN message */
  		if (!msg_connected(msg) && !(msg_errcode(msg)))
  			retval = TIPC_OK;
  		break;
  	case SS_DISCONNECTING:
  		break;
  	default:
  		pr_err("Unknown socket state %u
  ", sock->state);
  	}
  	return retval;
  }
  
  /**
aba79f332   Ying Xue   tipc: byte-based ...
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
   * rcvbuf_limit - get proper overload limit of socket receive queue
   * @sk: socket
   * @buf: message
   *
   * For all connection oriented messages, irrespective of importance,
   * the default overload value (i.e. 67MB) is set as limit.
   *
   * For all connectionless messages, by default new queue limits are
   * as belows:
   *
cc79dd1ba   Ying Xue   tipc: change sock...
1330
1331
1332
1333
   * TIPC_LOW_IMPORTANCE       (4 MB)
   * TIPC_MEDIUM_IMPORTANCE    (8 MB)
   * TIPC_HIGH_IMPORTANCE      (16 MB)
   * TIPC_CRITICAL_IMPORTANCE  (32 MB)
aba79f332   Ying Xue   tipc: byte-based ...
1334
1335
1336
1337
1338
1339
   *
   * Returns overload limit according to corresponding message importance
   */
  static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf)
  {
  	struct tipc_msg *msg = buf_msg(buf);
aba79f332   Ying Xue   tipc: byte-based ...
1340
1341
  
  	if (msg_connected(msg))
0cee6bbe0   wangweidong   tipc: remove unne...
1342
1343
1344
1345
  		return sysctl_tipc_rmem[2];
  
  	return sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE <<
  		msg_importance(msg);
aba79f332   Ying Xue   tipc: byte-based ...
1346
1347
1348
  }
  
  /**
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1349
1350
   * filter_rcv - validate incoming message
   * @sk: socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
1351
   * @buf: message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1352
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1353
1354
1355
1356
   * Enqueues message on receive queue if acceptable; optionally handles
   * disconnect indication for a connected socket.
   *
   * Called with socket lock already taken; port lock may also be taken.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1357
   *
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1358
1359
   * Returns 0 (TIPC_OK) if message was consumed, -TIPC error code if message
   * to be rejected.
b97bf3fd8   Per Liden   [TIPC] Initial merge
1360
   */
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1361
  static int filter_rcv(struct sock *sk, struct sk_buff *buf)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1362
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1363
  	struct socket *sock = sk->sk_socket;
58ed94424   Jon Paul Maloy   tipc: align usage...
1364
  	struct tipc_sock *tsk = tipc_sk(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1365
  	struct tipc_msg *msg = buf_msg(buf);
aba79f332   Ying Xue   tipc: byte-based ...
1366
  	unsigned int limit = rcvbuf_limit(sk, buf);
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1367
  	int rc = TIPC_OK;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1368

b97bf3fd8   Per Liden   [TIPC] Initial merge
1369
  	/* Reject message if it is wrong sort of message for socket */
aad585473   Allan Stephens   tipc: Reject payl...
1370
  	if (msg_type(msg) > TIPC_DIRECT_MSG)
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1371
  		return -TIPC_ERR_NO_PORT;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1372

b97bf3fd8   Per Liden   [TIPC] Initial merge
1373
  	if (sock->state == SS_READY) {
b29f14284   Allan Stephens   tipc: remove call...
1374
  		if (msg_connected(msg))
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1375
  			return -TIPC_ERR_NO_PORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1376
  	} else {
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1377
1378
1379
  		rc = filter_connect(tsk, &buf);
  		if (rc != TIPC_OK || buf == NULL)
  			return rc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1380
1381
1382
  	}
  
  	/* Reject message if there isn't room to queue it */
aba79f332   Ying Xue   tipc: byte-based ...
1383
  	if (sk_rmem_alloc_get(sk) + buf->truesize >= limit)
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1384
  		return -TIPC_ERR_OVERLOAD;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1385

aba79f332   Ying Xue   tipc: byte-based ...
1386
  	/* Enqueue message */
406824320   Ying Xue   tipc: silence spa...
1387
  	TIPC_SKB_CB(buf)->handle = NULL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1388
  	__skb_queue_tail(&sk->sk_receive_queue, buf);
aba79f332   Ying Xue   tipc: byte-based ...
1389
  	skb_set_owner_r(buf, sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1390

676d23690   David S. Miller   net: Fix use afte...
1391
  	sk->sk_data_ready(sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1392
1393
  	return TIPC_OK;
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
1394

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1395
  /**
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1396
   * tipc_backlog_rcv - handle incoming message from backlog queue
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1397
1398
1399
1400
1401
1402
1403
   * @sk: socket
   * @buf: message
   *
   * Caller must hold socket lock, but not port lock.
   *
   * Returns 0
   */
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1404
  static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *buf)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1405
  {
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1406
  	int rc;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
1407
  	u32 onode;
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1408
  	struct tipc_sock *tsk = tipc_sk(sk);
02c00c2ab   Jon Paul Maloy   tipc: fix potenti...
1409
  	uint truesize = buf->truesize;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1410

e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1411
  	rc = filter_rcv(sk, buf);
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1412

8db1bae30   Jon Paul Maloy   tipc: separate bu...
1413
1414
1415
  	if (unlikely(rc && tipc_msg_reverse(buf, &onode, -rc)))
  		tipc_link_xmit2(buf, onode, 0);
  	else if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT)
02c00c2ab   Jon Paul Maloy   tipc: fix potenti...
1416
  		atomic_add(truesize, &tsk->dupl_rcvcnt);
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1417

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1418
1419
1420
1421
  	return 0;
  }
  
  /**
24be34b5a   Jon Paul Maloy   tipc: eliminate u...
1422
   * tipc_sk_rcv - handle incoming message
9816f0615   Jon Paul Maloy   tipc: merge port ...
1423
1424
1425
   * @buf: buffer containing arriving message
   * Consumes buffer
   * Returns 0 if success, or errno: -EHOSTUNREACH
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1426
   */
9816f0615   Jon Paul Maloy   tipc: merge port ...
1427
  int tipc_sk_rcv(struct sk_buff *buf)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1428
  {
9816f0615   Jon Paul Maloy   tipc: merge port ...
1429
1430
1431
1432
  	struct tipc_sock *tsk;
  	struct tipc_port *port;
  	struct sock *sk;
  	u32 dport = msg_destport(buf_msg(buf));
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1433
  	int rc = TIPC_OK;
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1434
  	uint limit;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
1435
  	u32 dnode;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  
  	/* Forward unresolved named message */
  	if (unlikely(!dport)) {
  		tipc_net_route_msg(buf);
  		return 0;
  	}
  
  	/* Validate destination */
  	port = tipc_port_lock(dport);
  	if (unlikely(!port)) {
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1446
  		rc = -TIPC_ERR_NO_PORT;
9816f0615   Jon Paul Maloy   tipc: merge port ...
1447
1448
1449
1450
1451
1452
1453
  		goto exit;
  	}
  
  	tsk = tipc_port_to_sock(port);
  	sk = &tsk->sk;
  
  	/* Queue message */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1454
  	bh_lock_sock(sk);
9816f0615   Jon Paul Maloy   tipc: merge port ...
1455

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1456
  	if (!sock_owned_by_user(sk)) {
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1457
  		rc = filter_rcv(sk, buf);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1458
  	} else {
4f4482dcd   Jon Paul Maloy   tipc: compensate ...
1459
1460
1461
1462
  		if (sk->sk_backlog.len == 0)
  			atomic_set(&tsk->dupl_rcvcnt, 0);
  		limit = rcvbuf_limit(sk, buf) + atomic_read(&tsk->dupl_rcvcnt);
  		if (sk_add_backlog(sk, buf, limit))
e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1463
  			rc = -TIPC_ERR_OVERLOAD;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1464
  	}
9816f0615   Jon Paul Maloy   tipc: merge port ...
1465

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1466
  	bh_unlock_sock(sk);
9816f0615   Jon Paul Maloy   tipc: merge port ...
1467
  	tipc_port_unlock(port);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1468

e4de5fab8   Jon Paul Maloy   tipc: use negativ...
1469
  	if (likely(!rc))
9816f0615   Jon Paul Maloy   tipc: merge port ...
1470
1471
  		return 0;
  exit:
8db1bae30   Jon Paul Maloy   tipc: separate bu...
1472
1473
1474
  	if (!tipc_msg_reverse(buf, &dnode, -rc))
  		return -EHOSTUNREACH;
  	tipc_link_xmit2(buf, dnode, 0);
9816f0615   Jon Paul Maloy   tipc: merge port ...
1475
  	return -EHOSTUNREACH;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1476
  }
78eb3a537   Ying Xue   tipc: standardize...
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
  static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
  {
  	struct sock *sk = sock->sk;
  	DEFINE_WAIT(wait);
  	int done;
  
  	do {
  		int err = sock_error(sk);
  		if (err)
  			return err;
  		if (!*timeo_p)
  			return -ETIMEDOUT;
  		if (signal_pending(current))
  			return sock_intr_errno(*timeo_p);
  
  		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  		done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING);
  		finish_wait(sk_sleep(sk), &wait);
  	} while (!done);
  	return 0;
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
1498
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1499
   * tipc_connect - establish a connection to another TIPC port
b97bf3fd8   Per Liden   [TIPC] Initial merge
1500
1501
1502
   * @sock: socket structure
   * @dest: socket address for destination port
   * @destlen: size of socket address data structure
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1503
   * @flags: file-related flags associated with socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
1504
1505
1506
   *
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1507
1508
  static int tipc_connect(struct socket *sock, struct sockaddr *dest,
  			int destlen, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1509
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1510
  	struct sock *sk = sock->sk;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1511
1512
  	struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
  	struct msghdr m = {NULL,};
78eb3a537   Ying Xue   tipc: standardize...
1513
1514
  	long timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout;
  	socket_state previous;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1515
  	int res;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1516
  	lock_sock(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1517
  	/* For now, TIPC does not allow use of connect() with DGRAM/RDM types */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1518
1519
1520
1521
  	if (sock->state == SS_READY) {
  		res = -EOPNOTSUPP;
  		goto exit;
  	}
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1522

b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1523
1524
1525
1526
1527
1528
  	/*
  	 * 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 ...
1529
1530
1531
1532
  	if (dst->addrtype == TIPC_ADDR_MCAST) {
  		res = -EINVAL;
  		goto exit;
  	}
78eb3a537   Ying Xue   tipc: standardize...
1533
  	previous = sock->state;
584d24b39   Ying Xue   tipc: introduce n...
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
  	switch (sock->state) {
  	case SS_UNCONNECTED:
  		/* Send a 'SYN-' to destination */
  		m.msg_name = dest;
  		m.msg_namelen = destlen;
  
  		/* If connect is in non-blocking case, set MSG_DONTWAIT to
  		 * indicate send_msg() is never blocked.
  		 */
  		if (!timeout)
  			m.msg_flags = MSG_DONTWAIT;
247f0f3c3   Ying Xue   tipc: align tipc ...
1545
  		res = tipc_sendmsg(NULL, sock, &m, 0);
584d24b39   Ying Xue   tipc: introduce n...
1546
1547
1548
1549
1550
1551
1552
1553
  		if ((res < 0) && (res != -EWOULDBLOCK))
  			goto exit;
  
  		/* Just entered SS_CONNECTING state; the only
  		 * difference is that return value in non-blocking
  		 * case is EINPROGRESS, rather than EALREADY.
  		 */
  		res = -EINPROGRESS;
584d24b39   Ying Xue   tipc: introduce n...
1554
  	case SS_CONNECTING:
78eb3a537   Ying Xue   tipc: standardize...
1555
1556
1557
1558
1559
1560
1561
  		if (previous == SS_CONNECTING)
  			res = -EALREADY;
  		if (!timeout)
  			goto exit;
  		timeout = msecs_to_jiffies(timeout);
  		/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
  		res = tipc_wait_for_connect(sock, &timeout);
584d24b39   Ying Xue   tipc: introduce n...
1562
1563
1564
1565
1566
1567
  		break;
  	case SS_CONNECTED:
  		res = -EISCONN;
  		break;
  	default:
  		res = -EINVAL;
78eb3a537   Ying Xue   tipc: standardize...
1568
  		break;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1569
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1570
1571
  exit:
  	release_sock(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1572
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1573
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1574
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1575
   * tipc_listen - allow socket to listen for incoming connections
b97bf3fd8   Per Liden   [TIPC] Initial merge
1576
1577
   * @sock: socket structure
   * @len: (unused)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1578
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1579
1580
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1581
  static int tipc_listen(struct socket *sock, int len)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1582
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1583
1584
1585
1586
  	struct sock *sk = sock->sk;
  	int res;
  
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1587

245f3d342   Ying Xue   tipc: Simplify pr...
1588
  	if (sock->state != SS_UNCONNECTED)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1589
1590
1591
1592
1593
1594
1595
1596
  		res = -EINVAL;
  	else {
  		sock->state = SS_LISTENING;
  		res = 0;
  	}
  
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1597
  }
6398e23cd   Ying Xue   tipc: standardize...
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
  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...
1612
  		if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
6398e23cd   Ying Xue   tipc: standardize...
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
  			release_sock(sk);
  			timeo = schedule_timeout(timeo);
  			lock_sock(sk);
  		}
  		err = 0;
  		if (!skb_queue_empty(&sk->sk_receive_queue))
  			break;
  		err = -EINVAL;
  		if (sock->state != SS_LISTENING)
  			break;
  		err = sock_intr_errno(timeo);
  		if (signal_pending(current))
  			break;
  		err = -EAGAIN;
  		if (!timeo)
  			break;
  	}
  	finish_wait(sk_sleep(sk), &wait);
  	return err;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1633
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1634
   * tipc_accept - wait for connection request
b97bf3fd8   Per Liden   [TIPC] Initial merge
1635
1636
1637
   * @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...
1638
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1639
1640
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1641
  static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1642
  {
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1643
  	struct sock *new_sk, *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1644
  	struct sk_buff *buf;
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1645
  	struct tipc_port *new_port;
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1646
  	struct tipc_msg *msg;
f9fef18c6   Jon Paul Maloy   tipc: remove redu...
1647
  	struct tipc_portid peer;
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1648
  	u32 new_ref;
6398e23cd   Ying Xue   tipc: standardize...
1649
  	long timeo;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1650
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1651

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

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1654
1655
  	if (sock->state != SS_LISTENING) {
  		res = -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1656
1657
  		goto exit;
  	}
6398e23cd   Ying Xue   tipc: standardize...
1658
1659
1660
1661
  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
  	res = tipc_wait_for_accept(sock, timeo);
  	if (res)
  		goto exit;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1662
1663
  
  	buf = skb_peek(&sk->sk_receive_queue);
c5fa7b3cf   Ying Xue   tipc: introduce n...
1664
  	res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1665
1666
  	if (res)
  		goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1667

0fef8f205   Paul Gortmaker   tipc: refactor ac...
1668
  	new_sk = new_sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1669
  	new_port = &tipc_sk(new_sk)->port;
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1670
  	new_ref = new_port->ref;
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1671
  	msg = buf_msg(buf);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1672

0fef8f205   Paul Gortmaker   tipc: refactor ac...
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
  	/* 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)
  	 */
  	reject_rx_queue(new_sk);
  
  	/* Connect new socket to it's peer */
f9fef18c6   Jon Paul Maloy   tipc: remove redu...
1683
1684
1685
  	peer.ref = msg_origport(msg);
  	peer.node = msg_orignode(msg);
  	tipc_port_connect(new_ref, &peer);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1686
  	new_sock->state = SS_CONNECTED;
3b4f302d8   Jon Paul Maloy   tipc: eliminate r...
1687
  	tipc_port_set_importance(new_port, msg_importance(msg));
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1688
  	if (msg_named(msg)) {
8826cde65   Jon Paul Maloy   tipc: aggregate p...
1689
1690
  		new_port->conn_type = msg_nametype(msg);
  		new_port->conn_instance = msg_nameinst(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1691
  	}
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1692
1693
1694
1695
1696
1697
1698
1699
1700
  
  	/*
  	 * 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,};
  
  		advance_rx_queue(sk);
247f0f3c3   Ying Xue   tipc: align tipc ...
1701
  		tipc_send_packet(NULL, new_sock, &m, 0);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1702
1703
1704
  	} else {
  		__skb_dequeue(&sk->sk_receive_queue);
  		__skb_queue_head(&new_sk->sk_receive_queue, buf);
aba79f332   Ying Xue   tipc: byte-based ...
1705
  		skb_set_owner_r(buf, new_sk);
0fef8f205   Paul Gortmaker   tipc: refactor ac...
1706
1707
  	}
  	release_sock(new_sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1708
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1709
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1710
1711
1712
1713
  	return res;
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1714
   * tipc_shutdown - shutdown socket connection
b97bf3fd8   Per Liden   [TIPC] Initial merge
1715
   * @sock: socket structure
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
1716
   * @how: direction to close (must be SHUT_RDWR)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1717
1718
   *
   * Terminates connection (if necessary), then purges socket's receive queue.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1719
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1720
1721
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1722
  static int tipc_shutdown(struct socket *sock, int how)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1723
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1724
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1725
1726
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_port *port = &tsk->port;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1727
  	struct sk_buff *buf;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
1728
  	u32 peer;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1729
  	int res;
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
1730
1731
  	if (how != SHUT_RDWR)
  		return -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1732

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1733
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1734
1735
  
  	switch (sock->state) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1736
  	case SS_CONNECTING:
b97bf3fd8   Per Liden   [TIPC] Initial merge
1737
  	case SS_CONNECTED:
b97bf3fd8   Per Liden   [TIPC] Initial merge
1738
  restart:
617d3c7a5   Paul Gortmaker   tipc: compress ou...
1739
  		/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1740
1741
  		buf = __skb_dequeue(&sk->sk_receive_queue);
  		if (buf) {
406824320   Ying Xue   tipc: silence spa...
1742
  			if (TIPC_SKB_CB(buf)->handle != NULL) {
5f6d9123f   Allan Stephens   tipc: Eliminate t...
1743
  				kfree_skb(buf);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1744
1745
  				goto restart;
  			}
58ed94424   Jon Paul Maloy   tipc: align usage...
1746
  			tipc_port_disconnect(port->ref);
8db1bae30   Jon Paul Maloy   tipc: separate bu...
1747
1748
  			if (tipc_msg_reverse(buf, &peer, TIPC_CONN_SHUTDOWN))
  				tipc_link_xmit2(buf, peer, 0);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1749
  		} else {
58ed94424   Jon Paul Maloy   tipc: align usage...
1750
  			tipc_port_shutdown(port->ref);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1751
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1752
1753
  
  		sock->state = SS_DISCONNECTING;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1754
1755
1756
1757
  
  		/* fall through */
  
  	case SS_DISCONNECTING:
750311510   Ying Xue   tipc: wake up all...
1758
  		/* Discard any unreceived messages */
57467e562   Ying Xue   tipc: eliminate d...
1759
  		__skb_queue_purge(&sk->sk_receive_queue);
750311510   Ying Xue   tipc: wake up all...
1760
1761
1762
  
  		/* Wake up anyone sleeping in poll */
  		sk->sk_state_change(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1763
1764
1765
1766
1767
1768
  		res = 0;
  		break;
  
  	default:
  		res = -ENOTCONN;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1769
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1770
1771
1772
1773
  	return res;
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1774
   * tipc_setsockopt - set socket option
b97bf3fd8   Per Liden   [TIPC] Initial merge
1775
1776
1777
1778
1779
   * @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...
1780
1781
   *
   * For stream sockets only, accepts and ignores all IPPROTO_TCP options
b97bf3fd8   Per Liden   [TIPC] Initial merge
1782
   * (to ease compatibility).
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1783
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1784
1785
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1786
1787
  static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
  			   char __user *ov, unsigned int ol)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1788
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1789
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1790
1791
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_port *port = &tsk->port;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1792
1793
  	u32 value;
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1794
1795
  	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
  		return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1796
1797
1798
1799
  	if (lvl != SOL_TIPC)
  		return -ENOPROTOOPT;
  	if (ol < sizeof(value))
  		return -EINVAL;
2db9983a4   Allan Stephens   tipc: split varia...
1800
1801
  	res = get_user(value, (u32 __user *)ov);
  	if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1802
  		return res;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1803
  	lock_sock(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1804

b97bf3fd8   Per Liden   [TIPC] Initial merge
1805
1806
  	switch (opt) {
  	case TIPC_IMPORTANCE:
58ed94424   Jon Paul Maloy   tipc: align usage...
1807
  		tipc_port_set_importance(port, value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1808
1809
1810
  		break;
  	case TIPC_SRC_DROPPABLE:
  		if (sock->type != SOCK_STREAM)
58ed94424   Jon Paul Maloy   tipc: align usage...
1811
  			tipc_port_set_unreliable(port, value);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1812
  		else
b97bf3fd8   Per Liden   [TIPC] Initial merge
1813
1814
1815
  			res = -ENOPROTOOPT;
  		break;
  	case TIPC_DEST_DROPPABLE:
58ed94424   Jon Paul Maloy   tipc: align usage...
1816
  		tipc_port_set_unreturnable(port, value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1817
1818
  		break;
  	case TIPC_CONN_TIMEOUT:
a0f40f02e   Allan Stephens   tipc: Prevent rou...
1819
  		tipc_sk(sk)->conn_timeout = value;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1820
  		/* no need to set "res", since already 0 at this point */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1821
1822
1823
1824
  		break;
  	default:
  		res = -EINVAL;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1825
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1826
1827
1828
1829
  	return res;
  }
  
  /**
247f0f3c3   Ying Xue   tipc: align tipc ...
1830
   * tipc_getsockopt - get socket option
b97bf3fd8   Per Liden   [TIPC] Initial merge
1831
1832
1833
1834
1835
   * @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...
1836
1837
   *
   * For stream sockets only, returns 0 length result for all IPPROTO_TCP options
b97bf3fd8   Per Liden   [TIPC] Initial merge
1838
   * (to ease compatibility).
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1839
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1840
1841
   * Returns 0 on success, errno otherwise
   */
247f0f3c3   Ying Xue   tipc: align tipc ...
1842
1843
  static int tipc_getsockopt(struct socket *sock, int lvl, int opt,
  			   char __user *ov, int __user *ol)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1844
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1845
  	struct sock *sk = sock->sk;
58ed94424   Jon Paul Maloy   tipc: align usage...
1846
1847
  	struct tipc_sock *tsk = tipc_sk(sk);
  	struct tipc_port *port = &tsk->port;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1848
  	int len;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1849
  	u32 value;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1850
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1851

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1852
1853
  	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
  		return put_user(0, ol);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1854
1855
  	if (lvl != SOL_TIPC)
  		return -ENOPROTOOPT;
2db9983a4   Allan Stephens   tipc: split varia...
1856
1857
  	res = get_user(len, ol);
  	if (res)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1858
  		return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1859

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1860
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1861
1862
1863
  
  	switch (opt) {
  	case TIPC_IMPORTANCE:
58ed94424   Jon Paul Maloy   tipc: align usage...
1864
  		value = tipc_port_importance(port);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1865
1866
  		break;
  	case TIPC_SRC_DROPPABLE:
58ed94424   Jon Paul Maloy   tipc: align usage...
1867
  		value = tipc_port_unreliable(port);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1868
1869
  		break;
  	case TIPC_DEST_DROPPABLE:
58ed94424   Jon Paul Maloy   tipc: align usage...
1870
  		value = tipc_port_unreturnable(port);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1871
1872
  		break;
  	case TIPC_CONN_TIMEOUT:
a0f40f02e   Allan Stephens   tipc: Prevent rou...
1873
  		value = tipc_sk(sk)->conn_timeout;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1874
  		/* no need to set "res", since already 0 at this point */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1875
  		break;
0e65967e3   Allan Stephens   tipc: cleanup var...
1876
  	case TIPC_NODE_RECVQ_DEPTH:
9da3d4758   Ying Xue   tipc: eliminate a...
1877
  		value = 0; /* was tipc_queue_size, now obsolete */
6650613d3   oscar.medina@motorola.com   tipc: Add socket ...
1878
  		break;
0e65967e3   Allan Stephens   tipc: cleanup var...
1879
  	case TIPC_SOCK_RECVQ_DEPTH:
6650613d3   oscar.medina@motorola.com   tipc: Add socket ...
1880
1881
  		value = skb_queue_len(&sk->sk_receive_queue);
  		break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1882
1883
1884
  	default:
  		res = -EINVAL;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1885
  	release_sock(sk);
25860c3bd   Paul Gortmaker   tipc: recode gets...
1886
1887
  	if (res)
  		return res;	/* "get" failed */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1888

25860c3bd   Paul Gortmaker   tipc: recode gets...
1889
1890
1891
1892
1893
1894
1895
  	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
1896
  }
78acb1f9b   Erik Hugne   tipc: add ioctl t...
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
  int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg)
  {
  	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;
  		if (!tipc_node_get_linkname(lnr.bearer_id, lnr.peer,
  					    lnr.linkname, TIPC_MAX_LINK_NAME)) {
  			if (copy_to_user(argp, &lnr, sizeof(lnr)))
  				return -EFAULT;
  			return 0;
  		}
  		return -EADDRNOTAVAIL;
  		break;
  	default:
  		return -ENOIOCTLCMD;
  	}
  }
ae86b9e38   Ben Hutchings   net: Fix non-kern...
1918
  /* Protocol switches for the various types of TIPC sockets */
bca65eae3   Florian Westphal   [TIPC]: declare p...
1919
  static const struct proto_ops msg_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1920
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1921
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
1922
1923
1924
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1925
  	.socketpair	= sock_no_socketpair,
245f3d342   Ying Xue   tipc: Simplify pr...
1926
  	.accept		= sock_no_accept,
247f0f3c3   Ying Xue   tipc: align tipc ...
1927
1928
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
1929
  	.ioctl		= tipc_ioctl,
245f3d342   Ying Xue   tipc: Simplify pr...
1930
  	.listen		= sock_no_listen,
247f0f3c3   Ying Xue   tipc: align tipc ...
1931
1932
1933
1934
1935
  	.shutdown	= tipc_shutdown,
  	.setsockopt	= tipc_setsockopt,
  	.getsockopt	= tipc_getsockopt,
  	.sendmsg	= tipc_sendmsg,
  	.recvmsg	= tipc_recvmsg,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1936
1937
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
1938
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
1939
  static const struct proto_ops packet_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1940
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1941
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
1942
1943
1944
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1945
  	.socketpair	= sock_no_socketpair,
247f0f3c3   Ying Xue   tipc: align tipc ...
1946
1947
1948
  	.accept		= tipc_accept,
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
1949
  	.ioctl		= tipc_ioctl,
247f0f3c3   Ying Xue   tipc: align tipc ...
1950
1951
1952
1953
1954
1955
  	.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...
1956
1957
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
1958
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
1959
  static const struct proto_ops stream_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1960
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1961
  	.family		= AF_TIPC,
247f0f3c3   Ying Xue   tipc: align tipc ...
1962
1963
1964
  	.release	= tipc_release,
  	.bind		= tipc_bind,
  	.connect	= tipc_connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1965
  	.socketpair	= sock_no_socketpair,
247f0f3c3   Ying Xue   tipc: align tipc ...
1966
1967
1968
  	.accept		= tipc_accept,
  	.getname	= tipc_getname,
  	.poll		= tipc_poll,
78acb1f9b   Erik Hugne   tipc: add ioctl t...
1969
  	.ioctl		= tipc_ioctl,
247f0f3c3   Ying Xue   tipc: align tipc ...
1970
1971
1972
1973
1974
1975
  	.listen		= tipc_listen,
  	.shutdown	= tipc_shutdown,
  	.setsockopt	= tipc_setsockopt,
  	.getsockopt	= tipc_getsockopt,
  	.sendmsg	= tipc_send_stream,
  	.recvmsg	= tipc_recv_stream,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1976
1977
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
1978
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
1979
  static const struct net_proto_family tipc_family_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1980
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1981
  	.family		= AF_TIPC,
c5fa7b3cf   Ying Xue   tipc: introduce n...
1982
  	.create		= tipc_sk_create
b97bf3fd8   Per Liden   [TIPC] Initial merge
1983
1984
1985
1986
1987
  };
  
  static struct proto tipc_proto = {
  	.name		= "TIPC",
  	.owner		= THIS_MODULE,
cc79dd1ba   Ying Xue   tipc: change sock...
1988
1989
  	.obj_size	= sizeof(struct tipc_sock),
  	.sysctl_rmem	= sysctl_tipc_rmem
b97bf3fd8   Per Liden   [TIPC] Initial merge
1990
  };
c5fa7b3cf   Ying Xue   tipc: introduce n...
1991
1992
1993
1994
1995
  static struct proto tipc_proto_kern = {
  	.name		= "TIPC",
  	.obj_size	= sizeof(struct tipc_sock),
  	.sysctl_rmem	= sysctl_tipc_rmem
  };
b97bf3fd8   Per Liden   [TIPC] Initial merge
1996
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
1997
   * tipc_socket_init - initialize TIPC socket interface
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1998
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1999
2000
   * Returns 0 on success, errno otherwise
   */
4323add67   Per Liden   [TIPC] Avoid poll...
2001
  int tipc_socket_init(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2002
2003
  {
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
2004
  	res = proto_register(&tipc_proto, 1);
b97bf3fd8   Per Liden   [TIPC] Initial merge
2005
  	if (res) {
2cf8aa19f   Erik Hugne   tipc: use standar...
2006
2007
  		pr_err("Failed to register TIPC protocol type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
2008
2009
2010
2011
2012
  		goto out;
  	}
  
  	res = sock_register(&tipc_family_ops);
  	if (res) {
2cf8aa19f   Erik Hugne   tipc: use standar...
2013
2014
  		pr_err("Failed to register TIPC socket type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
2015
2016
2017
  		proto_unregister(&tipc_proto);
  		goto out;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
2018
2019
2020
2021
2022
   out:
  	return res;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
2023
   * tipc_socket_stop - stop TIPC socket interface
b97bf3fd8   Per Liden   [TIPC] Initial merge
2024
   */
4323add67   Per Liden   [TIPC] Avoid poll...
2025
  void tipc_socket_stop(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
2026
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
2027
2028
2029
  	sock_unregister(tipc_family_ops.family);
  	proto_unregister(&tipc_proto);
  }