Blame view

net/tipc/socket.c 46 KB
b97bf3fd8   Per Liden   [TIPC] Initial merge
1
2
  /*
   * net/tipc/socket.c: TIPC socket API
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
3
   *
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
4
   * Copyright (c) 2001-2007, Ericsson AB
4132facae   Allan Stephens   tipc: Remove unus...
5
   * Copyright (c) 2004-2008, 2010-2011, 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.
   */
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
36
  #include <linux/export.h>
b97bf3fd8   Per Liden   [TIPC] Initial merge
37
  #include <net/sock.h>
b97bf3fd8   Per Liden   [TIPC] Initial merge
38
  #include "core.h"
d265fef6d   Allan Stephens   tipc: Remove obso...
39
  #include "port.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
40
41
42
  
  #define SS_LISTENING	-1	/* socket is listening */
  #define SS_READY	-2	/* socket is connectionless */
3654ea02f   Allan Stephens   [TIPC]: Improve s...
43
44
  #define OVERLOAD_LIMIT_BASE	5000
  #define CONN_TIMEOUT_DEFAULT	8000	/* default connect timeout = 8s */
b97bf3fd8   Per Liden   [TIPC] Initial merge
45
46
47
48
  
  struct tipc_sock {
  	struct sock sk;
  	struct tipc_port *p;
2da59918e   Allan Stephens   tipc: Fix race co...
49
  	struct tipc_portid peer_name;
a0f40f02e   Allan Stephens   tipc: Prevent rou...
50
  	unsigned int conn_timeout;
b97bf3fd8   Per Liden   [TIPC] Initial merge
51
  };
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
52
53
  #define tipc_sk(sk) ((struct tipc_sock *)(sk))
  #define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
b97bf3fd8   Per Liden   [TIPC] Initial merge
54

71092ea12   Allan Stephens   tipc: Add support...
55
56
  #define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \
  			(sock->state == SS_DISCONNECTING))
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
57
  static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
b97bf3fd8   Per Liden   [TIPC] Initial merge
58
59
  static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
  static void wakeupdispatch(struct tipc_port *tport);
bca65eae3   Florian Westphal   [TIPC]: declare p...
60
61
62
  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
63
64
  
  static struct proto tipc_proto;
e3ec9c7d5   Allan Stephens   tipc: remove zero...
65
  static int sockets_enabled;
b97bf3fd8   Per Liden   [TIPC] Initial merge
66
67
  
  static atomic_t tipc_queue_size = ATOMIC_INIT(0);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
68
  /*
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
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
104
105
106
107
108
109
110
111
112
113
114
115
116
   * 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
   */
  
  /**
   * advance_rx_queue - discard first buffer in socket receive queue
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
117
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
118
119
  
  static void advance_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
120
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
121
122
  	buf_discard(__skb_dequeue(&sk->sk_receive_queue));
  	atomic_dec(&tipc_queue_size);
b97bf3fd8   Per Liden   [TIPC] Initial merge
123
  }
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
124
125
126
127
  /**
   * discard_rx_queue - discard all buffers in socket receive queue
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
128
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
129
130
  
  static void discard_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
131
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
132
133
134
135
136
137
  	struct sk_buff *buf;
  
  	while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
  		atomic_dec(&tipc_queue_size);
  		buf_discard(buf);
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
138
139
140
  }
  
  /**
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
141
142
143
   * reject_rx_queue - reject all buffers in socket receive queue
   *
   * Caller must hold socket lock
b97bf3fd8   Per Liden   [TIPC] Initial merge
144
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
145
  static void reject_rx_queue(struct sock *sk)
b97bf3fd8   Per Liden   [TIPC] Initial merge
146
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
147
148
149
150
151
152
  	struct sk_buff *buf;
  
  	while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
  		tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
  		atomic_dec(&tipc_queue_size);
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
153
154
155
156
  }
  
  /**
   * tipc_create - create a TIPC socket
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
157
   * @net: network namespace (must be default network)
b97bf3fd8   Per Liden   [TIPC] Initial merge
158
159
   * @sock: pre-allocated socket structure
   * @protocol: protocol indicator (must be 0)
3f378b684   Eric Paris   net: pass kern to...
160
   * @kern: caused by kernel or by userspace?
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
161
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
162
163
   * This routine creates additional data structures used by the TIPC socket,
   * initializes them, and links them together.
b97bf3fd8   Per Liden   [TIPC] Initial merge
164
165
166
   *
   * Returns 0 on success, errno otherwise
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
167

3f378b684   Eric Paris   net: pass kern to...
168
169
  static int tipc_create(struct net *net, struct socket *sock, int protocol,
  		       int kern)
b97bf3fd8   Per Liden   [TIPC] Initial merge
170
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
171
172
  	const struct proto_ops *ops;
  	socket_state state;
b97bf3fd8   Per Liden   [TIPC] Initial merge
173
  	struct sock *sk;
7ef43ebaa   Allan Stephens   tipc: Fix race co...
174
  	struct tipc_port *tp_ptr;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
175
176
  
  	/* Validate arguments */
b97bf3fd8   Per Liden   [TIPC] Initial merge
177

b97bf3fd8   Per Liden   [TIPC] Initial merge
178
179
  	if (unlikely(protocol != 0))
  		return -EPROTONOSUPPORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
180
181
  	switch (sock->type) {
  	case SOCK_STREAM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
182
183
  		ops = &stream_ops;
  		state = SS_UNCONNECTED;
b97bf3fd8   Per Liden   [TIPC] Initial merge
184
185
  		break;
  	case SOCK_SEQPACKET:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
186
187
  		ops = &packet_ops;
  		state = SS_UNCONNECTED;
b97bf3fd8   Per Liden   [TIPC] Initial merge
188
189
  		break;
  	case SOCK_DGRAM:
b97bf3fd8   Per Liden   [TIPC] Initial merge
190
  	case SOCK_RDM:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
191
192
  		ops = &msg_ops;
  		state = SS_READY;
b97bf3fd8   Per Liden   [TIPC] Initial merge
193
  		break;
499786516   Allan Stephens   [TIPC]: Improved ...
194
  	default:
499786516   Allan Stephens   [TIPC]: Improved ...
195
  		return -EPROTOTYPE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
196
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
197
  	/* Allocate socket's protocol area */
6257ff217   Pavel Emelyanov   [NET]: Forget the...
198
  	sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
199
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
200
  		return -ENOMEM;
b97bf3fd8   Per Liden   [TIPC] Initial merge
201

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
202
  	/* Allocate TIPC port for socket to use */
b97bf3fd8   Per Liden   [TIPC] Initial merge
203

0ea522416   Allan Stephens   tipc: Remove unne...
204
205
206
  	tp_ptr = tipc_createport_raw(sk, &dispatch, &wakeupdispatch,
  				     TIPC_LOW_IMPORTANCE);
  	if (unlikely(!tp_ptr)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
207
208
209
  		sk_free(sk);
  		return -ENOMEM;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
210

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
211
  	/* Finish initializing socket data structures */
b97bf3fd8   Per Liden   [TIPC] Initial merge
212

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
213
214
  	sock->ops = ops;
  	sock->state = state;
b97bf3fd8   Per Liden   [TIPC] Initial merge
215

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
216
  	sock_init_data(sock, sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
217
  	sk->sk_backlog_rcv = backlog_rcv;
0ea522416   Allan Stephens   tipc: Remove unne...
218
  	tipc_sk(sk)->p = tp_ptr;
a0f40f02e   Allan Stephens   tipc: Prevent rou...
219
  	tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
220

7ef43ebaa   Allan Stephens   tipc: Fix race co...
221
  	spin_unlock_bh(tp_ptr->lock);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
222
  	if (sock->state == SS_READY) {
0ea522416   Allan Stephens   tipc: Remove unne...
223
  		tipc_set_portunreturnable(tp_ptr->ref, 1);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
224
  		if (sock->type == SOCK_DGRAM)
0ea522416   Allan Stephens   tipc: Remove unne...
225
  			tipc_set_portunreliable(tp_ptr->ref, 1);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
226
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
227
228
229
230
231
232
233
234
235
236
237
238
239
  
  	return 0;
  }
  
  /**
   * release - destroy a TIPC socket
   * @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...
240
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
241
242
243
244
245
246
247
248
249
   * 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
   */
  
  static int release(struct socket *sock)
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
250
  	struct sock *sk = sock->sk;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
251
  	struct tipc_port *tport;
b97bf3fd8   Per Liden   [TIPC] Initial merge
252
  	struct sk_buff *buf;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
253
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
254

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
255
256
257
258
259
260
  	/*
  	 * Exit if socket isn't fully initialized (occurs when a failed accept()
  	 * releases a pre-allocated child socket that was never used)
  	 */
  
  	if (sk == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
261
  		return 0;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
262

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
263
264
265
266
267
268
269
  	tport = tipc_sk_port(sk);
  	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
270
271
  
  	while (sock->state != SS_DISCONNECTING) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
272
273
  		buf = __skb_dequeue(&sk->sk_receive_queue);
  		if (buf == NULL)
b97bf3fd8   Per Liden   [TIPC] Initial merge
274
  			break;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
275
  		atomic_dec(&tipc_queue_size);
0232fd0ac   Allan Stephens   tipc: Allow recei...
276
  		if (TIPC_SKB_CB(buf)->handle != 0)
b97bf3fd8   Per Liden   [TIPC] Initial merge
277
  			buf_discard(buf);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
278
279
280
281
282
283
  		else {
  			if ((sock->state == SS_CONNECTING) ||
  			    (sock->state == SS_CONNECTED)) {
  				sock->state = SS_DISCONNECTING;
  				tipc_disconnect(tport->ref);
  			}
b97bf3fd8   Per Liden   [TIPC] Initial merge
284
  			tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
285
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
286
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
287
288
289
290
  	/*
  	 * Delete TIPC port; this ensures no more messages are queued
  	 * (also disconnects an active connection & sends a 'FIN-' to peer)
  	 */
b97bf3fd8   Per Liden   [TIPC] Initial merge
291

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
292
  	res = tipc_deleteport(tport->ref);
b97bf3fd8   Per Liden   [TIPC] Initial merge
293

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
294
  	/* Discard any remaining (connection-based) messages in receive queue */
b97bf3fd8   Per Liden   [TIPC] Initial merge
295

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
296
  	discard_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
297

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
298
299
300
301
  	/* Reject any messages that accumulated in backlog queue */
  
  	sock->state = SS_DISCONNECTING;
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
302
303
  
  	sock_put(sk);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
304
  	sock->sk = NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
305

b97bf3fd8   Per Liden   [TIPC] Initial merge
306
307
308
309
310
311
312
313
  	return res;
  }
  
  /**
   * bind - associate or disassocate TIPC name(s) with a socket
   * @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...
314
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
315
316
317
   * 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...
318
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
319
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
320
321
322
   *
   * 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
323
324
325
326
   */
  
  static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
327
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
328
  	u32 portref = tipc_sk_port(sock->sk)->ref;
b97bf3fd8   Per Liden   [TIPC] Initial merge
329

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
330
331
  	if (unlikely(!uaddr_len))
  		return tipc_withdraw(portref, 0, NULL);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
332

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
333
334
335
336
  	if (uaddr_len < sizeof(struct sockaddr_tipc))
  		return -EINVAL;
  	if (addr->family != AF_TIPC)
  		return -EAFNOSUPPORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
337

b97bf3fd8   Per Liden   [TIPC] Initial merge
338
339
  	if (addr->addrtype == TIPC_ADDR_NAME)
  		addr->addr.nameseq.upper = addr->addr.nameseq.lower;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
340
341
  	else if (addr->addrtype != TIPC_ADDR_NAMESEQ)
  		return -EAFNOSUPPORT;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
342

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
343
344
345
  	return (addr->scope > 0) ?
  		tipc_publish(portref, addr->scope, &addr->addr.nameseq) :
  		tipc_withdraw(portref, -addr->scope, &addr->addr.nameseq);
b97bf3fd8   Per Liden   [TIPC] Initial merge
346
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
347
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
348
349
350
351
   * get_name - get port ID of socket or peer socket
   * @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...
352
   * @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
353
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
354
   * Returns 0 on success, errno otherwise
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
355
   *
2da59918e   Allan Stephens   tipc: Fix race co...
356
357
   * 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...
358
   *       a completely predictable manner).
b97bf3fd8   Per Liden   [TIPC] Initial merge
359
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
360
  static int get_name(struct socket *sock, struct sockaddr *uaddr,
b97bf3fd8   Per Liden   [TIPC] Initial merge
361
362
  		    int *uaddr_len, int peer)
  {
b97bf3fd8   Per Liden   [TIPC] Initial merge
363
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
2da59918e   Allan Stephens   tipc: Fix race co...
364
  	struct tipc_sock *tsock = tipc_sk(sock->sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
365

88f8a5e3e   Kulikov Vasiliy   net: tipc: fix in...
366
  	memset(addr, 0, sizeof(*addr));
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
367
  	if (peer) {
2da59918e   Allan Stephens   tipc: Fix race co...
368
369
370
371
372
  		if ((sock->state != SS_CONNECTED) &&
  			((peer != 2) || (sock->state != SS_DISCONNECTING)))
  			return -ENOTCONN;
  		addr->addr.id.ref = tsock->peer_name.ref;
  		addr->addr.id.node = tsock->peer_name.node;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
373
  	} else {
b924dcf00   Allan Stephens   tipc: Delete tipc...
374
375
  		addr->addr.id.ref = tsock->p->ref;
  		addr->addr.id.node = tipc_own_addr;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
376
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
377
378
379
380
381
  
  	*uaddr_len = sizeof(*addr);
  	addr->addrtype = TIPC_ADDR_ID;
  	addr->family = AF_TIPC;
  	addr->scope = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
382
  	addr->addr.name.domain = 0;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
383
  	return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
384
385
386
387
388
389
390
391
  }
  
  /**
   * poll - read and possibly block on pollmask
   * @file: file structure associated with the socket
   * @sock: socket for which to calculate the poll bits
   * @wait: ???
   *
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
392
393
394
395
396
397
398
399
400
   * 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...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
   *
   * socket state		flags set
   * ------------		---------
   * unconnected		no read flags
   *			no write flags
   *
   * 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
425
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
426
  static unsigned int poll(struct file *file, struct socket *sock,
b97bf3fd8   Per Liden   [TIPC] Initial merge
427
428
  			 poll_table *wait)
  {
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
429
  	struct sock *sk = sock->sk;
f662c0705   Allan Stephens   tipc: correct pro...
430
  	u32 mask = 0;
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
431

aa3951451   Eric Dumazet   net: sk_sleep() h...
432
  	poll_wait(file, sk_sleep(sk), wait);
9b674e82b   Allan Stephens   [TIPC]: Cosmetic ...
433

f662c0705   Allan Stephens   tipc: correct pro...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  	switch ((int)sock->state) {
  	case SS_READY:
  	case SS_CONNECTED:
  		if (!tipc_sk_port(sk)->congested)
  			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 ...
449
450
  
  	return mask;
b97bf3fd8   Per Liden   [TIPC] Initial merge
451
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
452
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
453
454
455
   * 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...
456
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
457
458
   * Prevents restricted configuration commands from being issued by
   * unauthorized users.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
459
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
460
461
   * Returns 0 if permission is granted, otherwise errno
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
462
  static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
b97bf3fd8   Per Liden   [TIPC] Initial merge
463
464
  {
  	struct tipc_cfg_msg_hdr hdr;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
465
466
467
468
  	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...
469
470
  	if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
  		return -EACCES;
b97bf3fd8   Per Liden   [TIPC] Initial merge
471

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

b97bf3fd8   Per Liden   [TIPC] Initial merge
479
480
481
482
483
  	return 0;
  }
  
  /**
   * send_msg - send message in connectionless manner
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
484
   * @iocb: if NULL, indicates that socket lock is already held
b97bf3fd8   Per Liden   [TIPC] Initial merge
485
486
   * @sock: socket structure
   * @m: message to send
e9024f0f7   Allan Stephens   [TIPC]: Non-opera...
487
   * @total_len: length of message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
488
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
489
   * Message must have an destination specified explicitly.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
490
   * Used for SOCK_RDM and SOCK_DGRAM messages,
b97bf3fd8   Per Liden   [TIPC] Initial merge
491
492
   * 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...
493
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
494
495
496
497
498
499
   * Returns the number of bytes sent on success, or errno otherwise
   */
  
  static int send_msg(struct kiocb *iocb, struct socket *sock,
  		    struct msghdr *m, size_t total_len)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
500
501
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
502
  	struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
b97bf3fd8   Per Liden   [TIPC] Initial merge
503
  	int needs_conn;
1d835874a   Ying Xue   tipc: Add support...
504
  	long timeout_val;
b97bf3fd8   Per Liden   [TIPC] Initial merge
505
506
507
508
  	int res = -EINVAL;
  
  	if (unlikely(!dest))
  		return -EDESTADDRREQ;
51f9cc1ff   Allan Stephens   [TIPC]: Optimized...
509
510
  	if (unlikely((m->msg_namelen < sizeof(*dest)) ||
  		     (dest->family != AF_TIPC)))
b97bf3fd8   Per Liden   [TIPC] Initial merge
511
  		return -EINVAL;
c29c3f70c   Allan Stephens   tipc: Abort exces...
512
513
514
  	if ((total_len > TIPC_MAX_USER_MSG_SIZE) ||
  	    (m->msg_iovlen > (unsigned)INT_MAX))
  		return -EMSGSIZE;
b97bf3fd8   Per Liden   [TIPC] Initial merge
515

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
516
517
  	if (iocb)
  		lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
518
519
  	needs_conn = (sock->state != SS_READY);
  	if (unlikely(needs_conn)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
520
521
522
523
524
525
526
527
528
529
530
531
532
  		if (sock->state == SS_LISTENING) {
  			res = -EPIPE;
  			goto exit;
  		}
  		if (sock->state != SS_UNCONNECTED) {
  			res = -EISCONN;
  			goto exit;
  		}
  		if ((tport->published) ||
  		    ((sock->type == SOCK_STREAM) && (total_len != 0))) {
  			res = -EOPNOTSUPP;
  			goto exit;
  		}
3388007bc   Allan Stephens   [TIPC]: Implied c...
533
  		if (dest->addrtype == TIPC_ADDR_NAME) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
534
535
  			tport->conn_type = dest->addr.name.name.type;
  			tport->conn_instance = dest->addr.name.name.instance;
3388007bc   Allan Stephens   [TIPC]: Implied c...
536
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
537
538
  
  		/* Abort any pending connection attempts (very unlikely) */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
539
  		reject_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
540
  	}
1d835874a   Ying Xue   tipc: Add support...
541
  	timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
542
543
  	do {
  		if (dest->addrtype == TIPC_ADDR_NAME) {
2db9983a4   Allan Stephens   tipc: split varia...
544
545
  			res = dest_name_check(dest, m);
  			if (res)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
546
547
  				break;
  			res = tipc_send2name(tport->ref,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
548
549
550
  					     &dest->addr.name.name,
  					     dest->addr.name.domain,
  					     m->msg_iovlen,
268969046   Allan Stephens   tipc: Avoid recom...
551
552
  					     m->msg_iov,
  					     total_len);
0e65967e3   Allan Stephens   tipc: cleanup var...
553
  		} else if (dest->addrtype == TIPC_ADDR_ID) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
554
  			res = tipc_send2port(tport->ref,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
555
556
  					     &dest->addr.id,
  					     m->msg_iovlen,
268969046   Allan Stephens   tipc: Avoid recom...
557
558
  					     m->msg_iov,
  					     total_len);
0e65967e3   Allan Stephens   tipc: cleanup var...
559
  		} else if (dest->addrtype == TIPC_ADDR_MCAST) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
560
561
  			if (needs_conn) {
  				res = -EOPNOTSUPP;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
562
  				break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
563
  			}
2db9983a4   Allan Stephens   tipc: split varia...
564
565
  			res = dest_name_check(dest, m);
  			if (res)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
566
567
  				break;
  			res = tipc_multicast(tport->ref,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
568
  					     &dest->addr.nameseq,
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
569
  					     m->msg_iovlen,
268969046   Allan Stephens   tipc: Avoid recom...
570
571
  					     m->msg_iov,
  					     total_len);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
572
573
  		}
  		if (likely(res != -ELINKCONG)) {
a016892cd   Allan Stephens   tipc: remove extr...
574
  			if (needs_conn && (res >= 0))
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
575
  				sock->state = SS_CONNECTING;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
576
  			break;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
577
  		}
1d835874a   Ying Xue   tipc: Add support...
578
579
  		if (timeout_val <= 0L) {
  			res = timeout_val ? timeout_val : -EWOULDBLOCK;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
580
  			break;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
581
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
582
  		release_sock(sk);
1d835874a   Ying Xue   tipc: Add support...
583
584
  		timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk),
  					       !tport->congested, timeout_val);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
585
  		lock_sock(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
586
  	} while (1);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
587
588
589
590
591
  
  exit:
  	if (iocb)
  		release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
592
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
593
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
594
   * send_packet - send a connection-oriented message
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
595
   * @iocb: if NULL, indicates that socket lock is already held
b97bf3fd8   Per Liden   [TIPC] Initial merge
596
597
   * @sock: socket structure
   * @m: message to send
e9024f0f7   Allan Stephens   [TIPC]: Non-opera...
598
   * @total_len: length of message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
599
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
600
   * Used for SOCK_SEQPACKET messages and SOCK_STREAM data.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
601
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
602
603
604
605
606
607
   * Returns the number of bytes sent on success, or errno otherwise
   */
  
  static int send_packet(struct kiocb *iocb, struct socket *sock,
  		       struct msghdr *m, size_t total_len)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
608
609
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
610
  	struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
1d835874a   Ying Xue   tipc: Add support...
611
  	long timeout_val;
b97bf3fd8   Per Liden   [TIPC] Initial merge
612
613
614
615
616
617
  	int res;
  
  	/* Handle implied connection establishment */
  
  	if (unlikely(dest))
  		return send_msg(iocb, sock, m, total_len);
c29c3f70c   Allan Stephens   tipc: Abort exces...
618
619
620
  	if ((total_len > TIPC_MAX_USER_MSG_SIZE) ||
  	    (m->msg_iovlen > (unsigned)INT_MAX))
  		return -EMSGSIZE;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
621
622
  	if (iocb)
  		lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
623

1d835874a   Ying Xue   tipc: Add support...
624
  	timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
625
  	do {
bdd94789d   Allan Stephens   [TIPC]: Connected...
626
627
  		if (unlikely(sock->state != SS_CONNECTED)) {
  			if (sock->state == SS_DISCONNECTING)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
628
  				res = -EPIPE;
bdd94789d   Allan Stephens   [TIPC]: Connected...
629
630
  			else
  				res = -ENOTCONN;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
631
  			break;
bdd94789d   Allan Stephens   [TIPC]: Connected...
632
  		}
268969046   Allan Stephens   tipc: Avoid recom...
633
634
  		res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov,
  				total_len);
a016892cd   Allan Stephens   tipc: remove extr...
635
  		if (likely(res != -ELINKCONG))
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
636
  			break;
1d835874a   Ying Xue   tipc: Add support...
637
638
  		if (timeout_val <= 0L) {
  			res = timeout_val ? timeout_val : -EWOULDBLOCK;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
639
  			break;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
640
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
641
  		release_sock(sk);
1d835874a   Ying Xue   tipc: Add support...
642
643
  		timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk),
  			(!tport->congested || !tport->connected), timeout_val);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
644
  		lock_sock(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
645
  	} while (1);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
646
647
648
649
  
  	if (iocb)
  		release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
650
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
651
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
652
653
654
655
656
   * send_stream - send stream-oriented data
   * @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...
657
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
658
   * Used for SOCK_STREAM data.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
659
660
   *
   * Returns the number of bytes sent on success (or partial success),
1303e8f17   Allan Stephens   [TIPC]: Stream so...
661
   * or errno if no data sent
b97bf3fd8   Per Liden   [TIPC] Initial merge
662
   */
b97bf3fd8   Per Liden   [TIPC] Initial merge
663
664
665
  static int send_stream(struct kiocb *iocb, struct socket *sock,
  		       struct msghdr *m, size_t total_len)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
666
667
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
668
669
670
671
672
  	struct msghdr my_msg;
  	struct iovec my_iov;
  	struct iovec *curr_iov;
  	int curr_iovlen;
  	char __user *curr_start;
05646c911   Allan Stephens   [TIPC]: Optimize ...
673
  	u32 hdr_size;
b97bf3fd8   Per Liden   [TIPC] Initial merge
674
675
  	int curr_left;
  	int bytes_to_send;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
676
  	int bytes_sent;
b97bf3fd8   Per Liden   [TIPC] Initial merge
677
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
678

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
679
  	lock_sock(sk);
05646c911   Allan Stephens   [TIPC]: Optimize ...
680
  	/* Handle special cases where there is no connection */
b97bf3fd8   Per Liden   [TIPC] Initial merge
681

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
682
  	if (unlikely(sock->state != SS_CONNECTED)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
683
684
685
686
687
688
689
690
691
692
  		if (sock->state == SS_UNCONNECTED) {
  			res = send_packet(NULL, sock, m, total_len);
  			goto exit;
  		} else if (sock->state == SS_DISCONNECTING) {
  			res = -EPIPE;
  			goto exit;
  		} else {
  			res = -ENOTCONN;
  			goto exit;
  		}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
693
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
694

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
695
696
697
698
  	if (unlikely(m->msg_name)) {
  		res = -EISCONN;
  		goto exit;
  	}
eb5959c2b   Allan Stephens   [TIPC]: Stream so...
699

c29c3f70c   Allan Stephens   tipc: Abort exces...
700
701
702
703
704
  	if ((total_len > (unsigned)INT_MAX) ||
  	    (m->msg_iovlen > (unsigned)INT_MAX)) {
  		res = -EMSGSIZE;
  		goto exit;
  	}
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
705
  	/*
b97bf3fd8   Per Liden   [TIPC] Initial merge
706
707
  	 * Send each iovec entry using one or more messages
  	 *
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
708
  	 * Note: This algorithm is good for the most likely case
b97bf3fd8   Per Liden   [TIPC] Initial merge
709
710
711
  	 * (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...
712
713
  	curr_iov = m->msg_iov;
  	curr_iovlen = m->msg_iovlen;
b97bf3fd8   Per Liden   [TIPC] Initial merge
714
715
  	my_msg.msg_iov = &my_iov;
  	my_msg.msg_iovlen = 1;
eb5959c2b   Allan Stephens   [TIPC]: Stream so...
716
717
  	my_msg.msg_flags = m->msg_flags;
  	my_msg.msg_name = NULL;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
718
  	bytes_sent = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
719

05646c911   Allan Stephens   [TIPC]: Optimize ...
720
  	hdr_size = msg_hdr_sz(&tport->phdr);
b97bf3fd8   Per Liden   [TIPC] Initial merge
721
722
723
724
725
  	while (curr_iovlen--) {
  		curr_start = curr_iov->iov_base;
  		curr_left = curr_iov->iov_len;
  
  		while (curr_left) {
05646c911   Allan Stephens   [TIPC]: Optimize ...
726
727
728
729
730
  			bytes_to_send = tport->max_pkt - hdr_size;
  			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
731
732
  			my_iov.iov_base = curr_start;
  			my_iov.iov_len = bytes_to_send;
268969046   Allan Stephens   tipc: Avoid recom...
733
  			res = send_packet(NULL, sock, &my_msg, bytes_to_send);
2db9983a4   Allan Stephens   tipc: split varia...
734
  			if (res < 0) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
735
  				if (bytes_sent)
05646c911   Allan Stephens   [TIPC]: Optimize ...
736
  					res = bytes_sent;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
737
  				goto exit;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
738
  			}
b97bf3fd8   Per Liden   [TIPC] Initial merge
739
740
  			curr_left -= bytes_to_send;
  			curr_start += bytes_to_send;
1303e8f17   Allan Stephens   [TIPC]: Stream so...
741
  			bytes_sent += bytes_to_send;
b97bf3fd8   Per Liden   [TIPC] Initial merge
742
743
744
745
  		}
  
  		curr_iov++;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
746
747
748
749
  	res = bytes_sent;
  exit:
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
750
751
752
753
754
  }
  
  /**
   * auto_connect - complete connection setup to a remote port
   * @sock: socket structure
b97bf3fd8   Per Liden   [TIPC] Initial merge
755
   * @msg: peer's response message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
756
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
757
758
   * Returns 0 on success, errno otherwise
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
759
  static int auto_connect(struct socket *sock, struct tipc_msg *msg)
b97bf3fd8   Per Liden   [TIPC] Initial merge
760
  {
2da59918e   Allan Stephens   tipc: Fix race co...
761
  	struct tipc_sock *tsock = tipc_sk(sock->sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
762
763
764
765
766
  
  	if (msg_errcode(msg)) {
  		sock->state = SS_DISCONNECTING;
  		return -ECONNREFUSED;
  	}
2da59918e   Allan Stephens   tipc: Fix race co...
767
768
769
770
  	tsock->peer_name.ref = msg_origport(msg);
  	tsock->peer_name.node = msg_orignode(msg);
  	tipc_connect2port(tsock->p->ref, &tsock->peer_name);
  	tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
b97bf3fd8   Per Liden   [TIPC] Initial merge
771
772
773
774
775
776
777
778
  	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...
779
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
780
781
   * Note: Address is not captured if not requested by receiver.
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
782
  static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
b97bf3fd8   Per Liden   [TIPC] Initial merge
783
  {
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
784
  	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name;
b97bf3fd8   Per Liden   [TIPC] Initial merge
785

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
786
  	if (addr) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
787
788
789
790
  		addr->family = AF_TIPC;
  		addr->addrtype = TIPC_ADDR_ID;
  		addr->addr.id.ref = msg_origport(msg);
  		addr->addr.id.node = msg_orignode(msg);
0e65967e3   Allan Stephens   tipc: cleanup var...
791
792
  		addr->addr.name.domain = 0;	/* could leave uninitialized */
  		addr->scope = 0;		/* could leave uninitialized */
b97bf3fd8   Per Liden   [TIPC] Initial merge
793
794
795
796
797
  		m->msg_namelen = sizeof(struct sockaddr_tipc);
  	}
  }
  
  /**
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
798
   * anc_data_recv - optionally capture ancillary data for received message
b97bf3fd8   Per Liden   [TIPC] Initial merge
799
800
801
   * @m: descriptor for message info
   * @msg: received message header
   * @tport: TIPC port associated with message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
802
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
803
   * Note: Ancillary data is not captured if not requested by receiver.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
804
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
805
806
   * Returns 0 if successful, otherwise errno
   */
05790c645   Sam Ravnborg   [TIPC]: Remove in...
807
  static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
b97bf3fd8   Per Liden   [TIPC] Initial merge
808
809
810
811
812
  				struct tipc_port *tport)
  {
  	u32 anc_data[3];
  	u32 err;
  	u32 dest_type;
3546c7508   Allan Stephens   [TIPC]: Can now r...
813
  	int has_name;
b97bf3fd8   Per Liden   [TIPC] Initial merge
814
815
816
817
818
819
820
821
822
823
824
  	int res;
  
  	if (likely(m->msg_controllen == 0))
  		return 0;
  
  	/* Optionally capture errored message object(s) */
  
  	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...
825
826
  		res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
827
  			return res;
2db9983a4   Allan Stephens   tipc: split varia...
828
829
830
831
832
833
  		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
834
835
836
837
838
839
840
  	}
  
  	/* Optionally capture message destination object */
  
  	dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
  	switch (dest_type) {
  	case TIPC_NAMED_MSG:
3546c7508   Allan Stephens   [TIPC]: Can now r...
841
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
842
843
844
845
846
  		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...
847
  		has_name = 1;
b97bf3fd8   Per Liden   [TIPC] Initial merge
848
849
850
851
852
  		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...
853
  		has_name = (tport->conn_type != 0);
b97bf3fd8   Per Liden   [TIPC] Initial merge
854
855
856
857
858
  		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...
859
  		has_name = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
860
  	}
2db9983a4   Allan Stephens   tipc: split varia...
861
862
863
864
865
  	if (has_name) {
  		res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data);
  		if (res)
  			return res;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
866
867
868
  
  	return 0;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
869
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
870
871
872
873
874
   * recv_msg - receive packet-oriented message
   * @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...
875
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
876
877
878
879
880
881
882
883
884
   * 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
   */
  
  static int recv_msg(struct kiocb *iocb, struct socket *sock,
  		    struct msghdr *m, size_t buf_len, int flags)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
885
886
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
887
888
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
71092ea12   Allan Stephens   tipc: Add support...
889
  	long timeout;
b97bf3fd8   Per Liden   [TIPC] Initial merge
890
891
892
  	unsigned int sz;
  	u32 err;
  	int res;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
893
  	/* Catch invalid receive requests */
b97bf3fd8   Per Liden   [TIPC] Initial merge
894

b97bf3fd8   Per Liden   [TIPC] Initial merge
895
896
  	if (unlikely(!buf_len))
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
897
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
898

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
899
900
  	if (unlikely(sock->state == SS_UNCONNECTED)) {
  		res = -ENOTCONN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
901
902
  		goto exit;
  	}
71092ea12   Allan Stephens   tipc: Add support...
903
  	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
904
  restart:
b97bf3fd8   Per Liden   [TIPC] Initial merge
905

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
906
  	/* Look for a message in receive queue; wait if necessary */
b97bf3fd8   Per Liden   [TIPC] Initial merge
907

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
908
909
910
911
912
  	while (skb_queue_empty(&sk->sk_receive_queue)) {
  		if (sock->state == SS_DISCONNECTING) {
  			res = -ENOTCONN;
  			goto exit;
  		}
71092ea12   Allan Stephens   tipc: Add support...
913
914
  		if (timeout <= 0L) {
  			res = timeout ? timeout : -EWOULDBLOCK;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
915
916
917
  			goto exit;
  		}
  		release_sock(sk);
71092ea12   Allan Stephens   tipc: Add support...
918
919
920
  		timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
  							   tipc_rx_ready(sock),
  							   timeout);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
921
  		lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
922
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
923
  	/* Look at first message in receive queue */
b97bf3fd8   Per Liden   [TIPC] Initial merge
924

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
925
  	buf = skb_peek(&sk->sk_receive_queue);
b97bf3fd8   Per Liden   [TIPC] Initial merge
926
927
928
929
930
931
932
  	msg = buf_msg(buf);
  	sz = msg_data_sz(msg);
  	err = msg_errcode(msg);
  
  	/* Complete connection setup for an implied connect */
  
  	if (unlikely(sock->state == SS_CONNECTING)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
933
934
  		res = auto_connect(sock, msg);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
935
936
937
938
939
940
  			goto exit;
  	}
  
  	/* Discard an empty non-errored message & try again */
  
  	if ((!sz) && (!err)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
941
  		advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
942
943
944
945
946
947
948
949
  		goto restart;
  	}
  
  	/* Capture sender's address (optional) */
  
  	set_orig_addr(m, msg);
  
  	/* Capture ancillary data (optional) */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
950
951
  	res = anc_data_recv(m, msg, tport);
  	if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
952
953
954
  		goto exit;
  
  	/* Capture message data (if valid) & compute return value (always) */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
955

b97bf3fd8   Per Liden   [TIPC] Initial merge
956
957
958
959
960
  	if (!err) {
  		if (unlikely(buf_len < sz)) {
  			sz = buf_len;
  			m->msg_flags |= MSG_TRUNC;
  		}
0232fd0ac   Allan Stephens   tipc: Allow recei...
961
962
963
  		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
  					      m->msg_iov, sz);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
964
  			goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
965
966
967
968
969
970
971
972
973
974
975
976
  		res = sz;
  	} else {
  		if ((sock->state == SS_READY) ||
  		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
  			res = 0;
  		else
  			res = -ECONNRESET;
  	}
  
  	/* Consume received message (optional) */
  
  	if (likely(!(flags & MSG_PEEK))) {
990098068   Allan Stephens   [TIPC]: Skip conn...
977
  		if ((sock->state != SS_READY) &&
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
978
979
980
  		    (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
  			tipc_acknowledge(tport->ref, tport->conn_unacked);
  		advance_rx_queue(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
981
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
982
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
983
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
984
985
  	return res;
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
986
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
987
988
989
990
991
   * recv_stream - receive stream-oriented data
   * @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...
992
993
   *
   * Used for SOCK_STREAM messages only.  If not enough data is available
b97bf3fd8   Per Liden   [TIPC] Initial merge
994
995
996
997
998
999
1000
1001
   * will optionally wait for more; never truncates data.
   *
   * Returns size of returned message data, errno otherwise
   */
  
  static int recv_stream(struct kiocb *iocb, struct socket *sock,
  		       struct msghdr *m, size_t buf_len, int flags)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1002
1003
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1004
1005
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
71092ea12   Allan Stephens   tipc: Add support...
1006
  	long timeout;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1007
  	unsigned int sz;
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1008
  	int sz_to_copy, target, needed;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1009
  	int sz_copied = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1010
  	u32 err;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1011
  	int res = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1012

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1013
  	/* Catch invalid receive attempts */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1014

b97bf3fd8   Per Liden   [TIPC] Initial merge
1015
1016
  	if (unlikely(!buf_len))
  		return -EINVAL;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1017
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1018

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1019
1020
1021
  	if (unlikely((sock->state == SS_UNCONNECTED) ||
  		     (sock->state == SS_CONNECTING))) {
  		res = -ENOTCONN;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1022
1023
  		goto exit;
  	}
3720d40b2   Florian Westphal   tipc: add SO_RCVL...
1024
  	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
71092ea12   Allan Stephens   tipc: Add support...
1025
  	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1026
  restart:
b97bf3fd8   Per Liden   [TIPC] Initial merge
1027

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1028
  	/* Look for a message in receive queue; wait if necessary */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1029

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1030
1031
1032
1033
1034
  	while (skb_queue_empty(&sk->sk_receive_queue)) {
  		if (sock->state == SS_DISCONNECTING) {
  			res = -ENOTCONN;
  			goto exit;
  		}
71092ea12   Allan Stephens   tipc: Add support...
1035
1036
  		if (timeout <= 0L) {
  			res = timeout ? timeout : -EWOULDBLOCK;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1037
1038
1039
  			goto exit;
  		}
  		release_sock(sk);
71092ea12   Allan Stephens   tipc: Add support...
1040
1041
1042
  		timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
  							   tipc_rx_ready(sock),
  							   timeout);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1043
  		lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1044
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1045
  	/* Look at first message in receive queue */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1046

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1047
  	buf = skb_peek(&sk->sk_receive_queue);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1048
1049
1050
1051
1052
1053
1054
  	msg = buf_msg(buf);
  	sz = msg_data_sz(msg);
  	err = msg_errcode(msg);
  
  	/* Discard an empty non-errored message & try again */
  
  	if ((!sz) && (!err)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1055
  		advance_rx_queue(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1056
1057
1058
1059
1060
1061
1062
  		goto restart;
  	}
  
  	/* Optionally capture sender's address & ancillary data of first msg */
  
  	if (sz_copied == 0) {
  		set_orig_addr(m, msg);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1063
1064
  		res = anc_data_recv(m, msg, tport);
  		if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1065
1066
1067
1068
  			goto exit;
  	}
  
  	/* Capture message data (if valid) & compute return value (always) */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1069

b97bf3fd8   Per Liden   [TIPC] Initial merge
1070
  	if (!err) {
0232fd0ac   Allan Stephens   tipc: Allow recei...
1071
  		u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1072

0232fd0ac   Allan Stephens   tipc: Allow recei...
1073
  		sz -= offset;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1074
1075
  		needed = (buf_len - sz_copied);
  		sz_to_copy = (sz <= needed) ? sz : needed;
0232fd0ac   Allan Stephens   tipc: Allow recei...
1076
1077
1078
1079
  
  		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
1080
  			goto exit;
0232fd0ac   Allan Stephens   tipc: Allow recei...
1081

b97bf3fd8   Per Liden   [TIPC] Initial merge
1082
1083
1084
1085
  		sz_copied += sz_to_copy;
  
  		if (sz_to_copy < sz) {
  			if (!(flags & MSG_PEEK))
0232fd0ac   Allan Stephens   tipc: Allow recei...
1086
1087
  				TIPC_SKB_CB(buf)->handle =
  				(void *)(unsigned long)(offset + sz_to_copy);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1088
1089
  			goto exit;
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
  	} 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) */
  
  	if (likely(!(flags & MSG_PEEK))) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1103
1104
1105
  		if (unlikely(++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
  			tipc_acknowledge(tport->ref, tport->conn_unacked);
  		advance_rx_queue(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1106
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1107
1108
  
  	/* Loop around if more data is required */
f64f9e719   Joe Perches   net: Move && and ...
1109
1110
  	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...
1111
  	    (sz_copied < target)) &&	/* and more is ready or required */
f64f9e719   Joe Perches   net: Move && and ...
1112
1113
  	    (!(flags & MSG_PEEK)) &&	/* and aren't just peeking at data */
  	    (!err))			/* and haven't reached a FIN */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1114
1115
1116
  		goto restart;
  
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1117
  	release_sock(sk);
a3b0a5a9d   Allan Stephens   [TIPC]: Simplify ...
1118
  	return sz_copied ? sz_copied : res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1119
1120
1121
  }
  
  /**
1819b8371   Allan Stephens   [TIPC]: Correct "...
1122
1123
   * rx_queue_full - determine if receive queue can accept another message
   * @msg: message to be added to queue
b97bf3fd8   Per Liden   [TIPC] Initial merge
1124
1125
   * @queue_size: current size of queue
   * @base: nominal maximum size of queue
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1126
   *
1819b8371   Allan Stephens   [TIPC]: Correct "...
1127
   * Returns 1 if queue is unable to accept message, 0 otherwise
b97bf3fd8   Per Liden   [TIPC] Initial merge
1128
   */
1819b8371   Allan Stephens   [TIPC]: Correct "...
1129
  static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
  {
  	u32 threshold;
  	u32 imp = msg_importance(msg);
  
  	if (imp == TIPC_LOW_IMPORTANCE)
  		threshold = base;
  	else if (imp == TIPC_MEDIUM_IMPORTANCE)
  		threshold = base * 2;
  	else if (imp == TIPC_HIGH_IMPORTANCE)
  		threshold = base * 100;
  	else
  		return 0;
  
  	if (msg_connected(msg))
  		threshold *= 4;
a02cec215   Eric Dumazet   net: return opera...
1145
  	return queue_size >= threshold;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1146
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1147
  /**
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1148
1149
   * filter_rcv - validate incoming message
   * @sk: socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
1150
   * @buf: message
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1151
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1152
1153
1154
1155
   * 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...
1156
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1157
1158
   * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1159
  static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1160
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1161
  	struct socket *sock = sk->sk_socket;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1162
  	struct tipc_msg *msg = buf_msg(buf);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1163
  	u32 recv_q_len;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1164
1165
1166
1167
1168
1169
1170
  	/* Reject message if it is wrong sort of message for socket */
  
  	/*
  	 * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD?
  	 * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
  	 * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
  	 */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1171

b97bf3fd8   Per Liden   [TIPC] Initial merge
1172
  	if (sock->state == SS_READY) {
b29f14284   Allan Stephens   tipc: remove call...
1173
  		if (msg_connected(msg))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1174
  			return TIPC_ERR_NO_PORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1175
  	} else {
b29f14284   Allan Stephens   tipc: remove call...
1176
  		if (msg_mcast(msg))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1177
  			return TIPC_ERR_NO_PORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1178
  		if (sock->state == SS_CONNECTED) {
b29f14284   Allan Stephens   tipc: remove call...
1179
  			if (!msg_connected(msg))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1180
  				return TIPC_ERR_NO_PORT;
b29f14284   Allan Stephens   tipc: remove call...
1181
1182
  		} else if (sock->state == SS_CONNECTING) {
  			if (!msg_connected(msg) && (msg_errcode(msg) == 0))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1183
  				return TIPC_ERR_NO_PORT;
b29f14284   Allan Stephens   tipc: remove call...
1184
1185
  		} else if (sock->state == SS_LISTENING) {
  			if (msg_connected(msg) || msg_errcode(msg))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1186
  				return TIPC_ERR_NO_PORT;
b29f14284   Allan Stephens   tipc: remove call...
1187
  		} else if (sock->state == SS_DISCONNECTING) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
1188
  			return TIPC_ERR_NO_PORT;
b29f14284   Allan Stephens   tipc: remove call...
1189
1190
  		} else /* (sock->state == SS_UNCONNECTED) */ {
  			if (msg_connected(msg) || msg_errcode(msg))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1191
  				return TIPC_ERR_NO_PORT;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1192
1193
1194
1195
  		}
  	}
  
  	/* Reject message if there isn't room to queue it */
1819b8371   Allan Stephens   [TIPC]: Correct "...
1196
1197
1198
  	recv_q_len = (u32)atomic_read(&tipc_queue_size);
  	if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
  		if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1199
  			return TIPC_ERR_OVERLOAD;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1200
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1201
  	recv_q_len = skb_queue_len(&sk->sk_receive_queue);
1819b8371   Allan Stephens   [TIPC]: Correct "...
1202
1203
  	if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
  		if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
b97bf3fd8   Per Liden   [TIPC] Initial merge
1204
  			return TIPC_ERR_OVERLOAD;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1205
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1206

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1207
  	/* Enqueue message (finally!) */
0232fd0ac   Allan Stephens   tipc: Allow recei...
1208
  	TIPC_SKB_CB(buf)->handle = 0;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1209
1210
  	atomic_inc(&tipc_queue_size);
  	__skb_queue_tail(&sk->sk_receive_queue, buf);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1211
1212
1213
1214
  	/* Initiate connection termination for an incoming 'FIN' */
  
  	if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
  		sock->state = SS_DISCONNECTING;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1215
  		tipc_disconnect_port(tipc_sk_port(sk));
b97bf3fd8   Per Liden   [TIPC] Initial merge
1216
  	}
aa3951451   Eric Dumazet   net: sk_sleep() h...
1217
1218
  	if (waitqueue_active(sk_sleep(sk)))
  		wake_up_interruptible(sk_sleep(sk));
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1219
1220
  	return TIPC_OK;
  }
b97bf3fd8   Per Liden   [TIPC] Initial merge
1221

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1222
1223
1224
1225
1226
1227
1228
1229
1230
  /**
   * backlog_rcv - handle incoming message from backlog queue
   * @sk: socket
   * @buf: message
   *
   * Caller must hold socket lock, but not port lock.
   *
   * Returns 0
   */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1231

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
  static int backlog_rcv(struct sock *sk, struct sk_buff *buf)
  {
  	u32 res;
  
  	res = filter_rcv(sk, buf);
  	if (res)
  		tipc_reject_msg(buf, res);
  	return 0;
  }
  
  /**
   * dispatch - handle incoming message
   * @tport: TIPC port that received message
   * @buf: message
   *
   * Called with port lock already taken.
   *
   * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
   */
  
  static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
  {
  	struct sock *sk = (struct sock *)tport->usr_handle;
  	u32 res;
  
  	/*
  	 * Process message if socket is unlocked; otherwise add to backlog queue
  	 *
  	 * This code is based on sk_receive_skb(), but must be distinct from it
  	 * since a TIPC-specific filter/reject mechanism is utilized
  	 */
  
  	bh_lock_sock(sk);
  	if (!sock_owned_by_user(sk)) {
  		res = filter_rcv(sk, buf);
  	} else {
a3a858ff1   Zhu Yi   net: backlog func...
1268
  		if (sk_add_backlog(sk, buf))
53eecb1be   Zhu Yi   tipc: use limited...
1269
1270
1271
  			res = TIPC_ERR_OVERLOAD;
  		else
  			res = TIPC_OK;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1272
1273
1274
1275
  	}
  	bh_unlock_sock(sk);
  
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1276
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1277
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
1278
1279
   * wakeupdispatch - wake up port after congestion
   * @tport: port to wakeup
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1280
   *
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1281
   * Called with port lock already taken.
b97bf3fd8   Per Liden   [TIPC] Initial merge
1282
1283
1284
1285
   */
  
  static void wakeupdispatch(struct tipc_port *tport)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1286
  	struct sock *sk = (struct sock *)tport->usr_handle;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1287

aa3951451   Eric Dumazet   net: sk_sleep() h...
1288
1289
  	if (waitqueue_active(sk_sleep(sk)))
  		wake_up_interruptible(sk_sleep(sk));
b97bf3fd8   Per Liden   [TIPC] Initial merge
1290
1291
1292
1293
1294
1295
1296
  }
  
  /**
   * connect - establish a connection to another TIPC port
   * @sock: socket structure
   * @dest: socket address for destination port
   * @destlen: size of socket address data structure
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1297
   * @flags: file-related flags associated with socket
b97bf3fd8   Per Liden   [TIPC] Initial merge
1298
1299
1300
   *
   * Returns 0 on success, errno otherwise
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1301
  static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1302
1303
  		   int flags)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1304
  	struct sock *sk = sock->sk;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1305
1306
1307
1308
  	struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
  	struct msghdr m = {NULL,};
  	struct sk_buff *buf;
  	struct tipc_msg *msg;
a0f40f02e   Allan Stephens   tipc: Prevent rou...
1309
  	unsigned int timeout;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1310
  	int res;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1311
  	lock_sock(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1312
  	/* For now, TIPC does not allow use of connect() with DGRAM/RDM types */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1313
1314
1315
1316
  	if (sock->state == SS_READY) {
  		res = -EOPNOTSUPP;
  		goto exit;
  	}
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1317
1318
  
  	/* For now, TIPC does not support the non-blocking form of connect() */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1319
  	if (flags & O_NONBLOCK) {
35997e315   Allan Stephens   tipc: Provide cor...
1320
  		res = -EOPNOTSUPP;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1321
1322
  		goto exit;
  	}
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1323
1324
  
  	/* Issue Posix-compliant error code if socket is in the wrong state */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
  	if (sock->state == SS_LISTENING) {
  		res = -EOPNOTSUPP;
  		goto exit;
  	}
  	if (sock->state == SS_CONNECTING) {
  		res = -EALREADY;
  		goto exit;
  	}
  	if (sock->state != SS_UNCONNECTED) {
  		res = -EISCONN;
  		goto exit;
  	}
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1337
1338
1339
1340
1341
1342
1343
  
  	/*
  	 * 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 ...
1344
1345
1346
1347
1348
1349
1350
1351
  	if (dst->addrtype == TIPC_ADDR_MCAST) {
  		res = -EINVAL;
  		goto exit;
  	}
  
  	/* Reject any messages already in receive queue (very unlikely) */
  
  	reject_rx_queue(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1352
1353
1354
1355
1356
1357
  
  	/* Send a 'SYN-' to destination */
  
  	m.msg_name = dest;
  	m.msg_namelen = destlen;
  	res = send_msg(NULL, sock, &m, 0);
a016892cd   Allan Stephens   tipc: remove extr...
1358
  	if (res < 0)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1359
  		goto exit;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1360

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1361
  	/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1362

564e83b51   Allan Stephens   tipc: Allow conne...
1363
  	timeout = tipc_sk(sk)->conn_timeout;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1364
  	release_sock(sk);
aa3951451   Eric Dumazet   net: sk_sleep() h...
1365
  	res = wait_event_interruptible_timeout(*sk_sleep(sk),
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1366
1367
  			(!skb_queue_empty(&sk->sk_receive_queue) ||
  			(sock->state != SS_CONNECTING)),
a0f40f02e   Allan Stephens   tipc: Prevent rou...
1368
1369
  			timeout ? (long)msecs_to_jiffies(timeout)
  				: MAX_SCHEDULE_TIMEOUT);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1370
  	lock_sock(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1371

b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1372
  	if (res > 0) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1373
1374
1375
1376
1377
1378
1379
1380
1381
  		buf = skb_peek(&sk->sk_receive_queue);
  		if (buf != NULL) {
  			msg = buf_msg(buf);
  			res = auto_connect(sock, msg);
  			if (!res) {
  				if (!msg_data_sz(msg))
  					advance_rx_queue(sk);
  			}
  		} else {
a016892cd   Allan Stephens   tipc: remove extr...
1382
  			if (sock->state == SS_CONNECTED)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1383
  				res = -EISCONN;
a016892cd   Allan Stephens   tipc: remove extr...
1384
  			else
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1385
  				res = -ECONNREFUSED;
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1386
1387
1388
1389
1390
1391
1392
1393
  		}
  	} else {
  		if (res == 0)
  			res = -ETIMEDOUT;
  		else
  			; /* leave "res" unchanged */
  		sock->state = SS_DISCONNECTING;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1394
1395
  exit:
  	release_sock(sk);
b89741a0c   Allan Stephens   [TIPC]: Cosmetic ...
1396
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1397
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1398
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
1399
1400
1401
   * listen - allow socket to listen for incoming connections
   * @sock: socket structure
   * @len: (unused)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1402
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1403
1404
1405
1406
1407
   * Returns 0 on success, errno otherwise
   */
  
  static int listen(struct socket *sock, int len)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1408
1409
1410
1411
  	struct sock *sk = sock->sk;
  	int res;
  
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1412

245f3d342   Ying Xue   tipc: Simplify pr...
1413
  	if (sock->state != SS_UNCONNECTED)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1414
1415
1416
1417
1418
1419
1420
1421
  		res = -EINVAL;
  	else {
  		sock->state = SS_LISTENING;
  		res = 0;
  	}
  
  	release_sock(sk);
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1422
  }
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1423
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
1424
1425
1426
1427
   * accept - wait for connection request
   * @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...
1428
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1429
1430
   * Returns 0 on success, errno otherwise
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1431
  static int accept(struct socket *sock, struct socket *new_sock, int flags)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1432
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1433
  	struct sock *sk = sock->sk;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1434
  	struct sk_buff *buf;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1435
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1436

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

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1439
1440
  	if (sock->state != SS_LISTENING) {
  		res = -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1441
1442
  		goto exit;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
1443

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1444
1445
1446
1447
1448
1449
  	while (skb_queue_empty(&sk->sk_receive_queue)) {
  		if (flags & O_NONBLOCK) {
  			res = -EWOULDBLOCK;
  			goto exit;
  		}
  		release_sock(sk);
aa3951451   Eric Dumazet   net: sk_sleep() h...
1450
  		res = wait_event_interruptible(*sk_sleep(sk),
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1451
1452
1453
1454
1455
1456
1457
  				(!skb_queue_empty(&sk->sk_receive_queue)));
  		lock_sock(sk);
  		if (res)
  			goto exit;
  	}
  
  	buf = skb_peek(&sk->sk_receive_queue);
3f378b684   Eric Paris   net: pass kern to...
1458
  	res = tipc_create(sock_net(sock->sk), new_sock, 0, 0);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1459
  	if (!res) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1460
  		struct sock *new_sk = new_sock->sk;
2da59918e   Allan Stephens   tipc: Fix race co...
1461
1462
  		struct tipc_sock *new_tsock = tipc_sk(new_sk);
  		struct tipc_port *new_tport = new_tsock->p;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1463
  		u32 new_ref = new_tport->ref;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1464
  		struct tipc_msg *msg = buf_msg(buf);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
  
  		lock_sock(new_sk);
  
  		/*
  		 * 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 */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1476

2da59918e   Allan Stephens   tipc: Fix race co...
1477
1478
1479
  		new_tsock->peer_name.ref = msg_origport(msg);
  		new_tsock->peer_name.node = msg_orignode(msg);
  		tipc_connect2port(new_ref, &new_tsock->peer_name);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1480
  		new_sock->state = SS_CONNECTED;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1481
1482
1483
  
  		tipc_set_portimportance(new_ref, msg_importance(msg));
  		if (msg_named(msg)) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1484
1485
  			new_tport->conn_type = msg_nametype(msg);
  			new_tport->conn_instance = msg_nameinst(msg);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1486
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1487
  		/*
b97bf3fd8   Per Liden   [TIPC] Initial merge
1488
1489
1490
  		 * Respond to 'SYN-' by discarding it & returning 'ACK'-.
  		 * Respond to 'SYN+' by queuing it on new socket.
  		 */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1491
1492
  		if (!msg_data_sz(msg)) {
  			struct msghdr m = {NULL,};
b97bf3fd8   Per Liden   [TIPC] Initial merge
1493

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1494
1495
  			advance_rx_queue(sk);
  			send_packet(NULL, new_sock, &m, 0);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1496
  		} else {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1497
1498
  			__skb_dequeue(&sk->sk_receive_queue);
  			__skb_queue_head(&new_sk->sk_receive_queue, buf);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1499
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1500
  		release_sock(new_sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1501
1502
  	}
  exit:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1503
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1504
1505
1506
1507
1508
1509
  	return res;
  }
  
  /**
   * shutdown - shutdown socket connection
   * @sock: socket structure
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
1510
   * @how: direction to close (must be SHUT_RDWR)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1511
1512
   *
   * Terminates connection (if necessary), then purges socket's receive queue.
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1513
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1514
1515
1516
1517
1518
   * Returns 0 on success, errno otherwise
   */
  
  static int shutdown(struct socket *sock, int how)
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1519
1520
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1521
1522
  	struct sk_buff *buf;
  	int res;
e247a8f5d   Allan Stephens   [TIPC]: Add argum...
1523
1524
  	if (how != SHUT_RDWR)
  		return -EINVAL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1525

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1526
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1527
1528
  
  	switch (sock->state) {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1529
  	case SS_CONNECTING:
b97bf3fd8   Per Liden   [TIPC] Initial merge
1530
  	case SS_CONNECTED:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1531
  		/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1532
  restart:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1533
1534
  		buf = __skb_dequeue(&sk->sk_receive_queue);
  		if (buf) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
1535
  			atomic_dec(&tipc_queue_size);
0232fd0ac   Allan Stephens   tipc: Allow recei...
1536
  			if (TIPC_SKB_CB(buf)->handle != 0) {
b97bf3fd8   Per Liden   [TIPC] Initial merge
1537
1538
1539
  				buf_discard(buf);
  				goto restart;
  			}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1540
  			tipc_disconnect(tport->ref);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1541
  			tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1542
1543
  		} else {
  			tipc_shutdown(tport->ref);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1544
  		}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1545
1546
  
  		sock->state = SS_DISCONNECTING;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1547
1548
1549
1550
  
  		/* fall through */
  
  	case SS_DISCONNECTING:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1551
  		/* Discard any unreceived messages; wake up sleeping tasks */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1552

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1553
  		discard_rx_queue(sk);
aa3951451   Eric Dumazet   net: sk_sleep() h...
1554
1555
  		if (waitqueue_active(sk_sleep(sk)))
  			wake_up_interruptible(sk_sleep(sk));
b97bf3fd8   Per Liden   [TIPC] Initial merge
1556
1557
1558
1559
1560
1561
  		res = 0;
  		break;
  
  	default:
  		res = -ENOTCONN;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1562
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
  	return res;
  }
  
  /**
   * setsockopt - set socket option
   * @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...
1573
1574
   *
   * For stream sockets only, accepts and ignores all IPPROTO_TCP options
b97bf3fd8   Per Liden   [TIPC] Initial merge
1575
   * (to ease compatibility).
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1576
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1577
1578
   * Returns 0 on success, errno otherwise
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1579
  static int setsockopt(struct socket *sock,
b7058842c   David S. Miller   net: Make setsock...
1580
  		      int lvl, int opt, char __user *ov, unsigned int ol)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1581
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1582
1583
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1584
1585
  	u32 value;
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1586
1587
  	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
  		return 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1588
1589
1590
1591
  	if (lvl != SOL_TIPC)
  		return -ENOPROTOOPT;
  	if (ol < sizeof(value))
  		return -EINVAL;
2db9983a4   Allan Stephens   tipc: split varia...
1592
1593
  	res = get_user(value, (u32 __user *)ov);
  	if (res)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1594
  		return res;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1595
  	lock_sock(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1596

b97bf3fd8   Per Liden   [TIPC] Initial merge
1597
1598
  	switch (opt) {
  	case TIPC_IMPORTANCE:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1599
  		res = tipc_set_portimportance(tport->ref, value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1600
1601
1602
  		break;
  	case TIPC_SRC_DROPPABLE:
  		if (sock->type != SOCK_STREAM)
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1603
  			res = tipc_set_portunreliable(tport->ref, value);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1604
  		else
b97bf3fd8   Per Liden   [TIPC] Initial merge
1605
1606
1607
  			res = -ENOPROTOOPT;
  		break;
  	case TIPC_DEST_DROPPABLE:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1608
  		res = tipc_set_portunreturnable(tport->ref, value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1609
1610
  		break;
  	case TIPC_CONN_TIMEOUT:
a0f40f02e   Allan Stephens   tipc: Prevent rou...
1611
  		tipc_sk(sk)->conn_timeout = value;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1612
  		/* no need to set "res", since already 0 at this point */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1613
1614
1615
1616
  		break;
  	default:
  		res = -EINVAL;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1617
  	release_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
  	return res;
  }
  
  /**
   * getsockopt - get socket option
   * @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...
1628
1629
   *
   * For stream sockets only, returns 0 length result for all IPPROTO_TCP options
b97bf3fd8   Per Liden   [TIPC] Initial merge
1630
   * (to ease compatibility).
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1631
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1632
1633
   * Returns 0 on success, errno otherwise
   */
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1634
  static int getsockopt(struct socket *sock,
28c4dadd3   Al Viro   [PATCH] tipc __us...
1635
  		      int lvl, int opt, char __user *ov, int __user *ol)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1636
  {
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1637
1638
  	struct sock *sk = sock->sk;
  	struct tipc_port *tport = tipc_sk_port(sk);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1639
  	int len;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1640
  	u32 value;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1641
  	int res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1642

c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1643
1644
  	if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
  		return put_user(0, ol);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1645
1646
  	if (lvl != SOL_TIPC)
  		return -ENOPROTOOPT;
2db9983a4   Allan Stephens   tipc: split varia...
1647
1648
  	res = get_user(len, ol);
  	if (res)
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1649
  		return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1650

0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1651
  	lock_sock(sk);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1652
1653
1654
  
  	switch (opt) {
  	case TIPC_IMPORTANCE:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1655
  		res = tipc_portimportance(tport->ref, &value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1656
1657
  		break;
  	case TIPC_SRC_DROPPABLE:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1658
  		res = tipc_portunreliable(tport->ref, &value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1659
1660
  		break;
  	case TIPC_DEST_DROPPABLE:
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1661
  		res = tipc_portunreturnable(tport->ref, &value);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1662
1663
  		break;
  	case TIPC_CONN_TIMEOUT:
a0f40f02e   Allan Stephens   tipc: Prevent rou...
1664
  		value = tipc_sk(sk)->conn_timeout;
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1665
  		/* no need to set "res", since already 0 at this point */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1666
  		break;
0e65967e3   Allan Stephens   tipc: cleanup var...
1667
  	case TIPC_NODE_RECVQ_DEPTH:
6650613d3   oscar.medina@motorola.com   tipc: Add socket ...
1668
1669
  		value = (u32)atomic_read(&tipc_queue_size);
  		break;
0e65967e3   Allan Stephens   tipc: cleanup var...
1670
  	case TIPC_SOCK_RECVQ_DEPTH:
6650613d3   oscar.medina@motorola.com   tipc: Add socket ...
1671
1672
  		value = skb_queue_len(&sk->sk_receive_queue);
  		break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
1673
1674
1675
  	default:
  		res = -EINVAL;
  	}
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1676
  	release_sock(sk);
25860c3bd   Paul Gortmaker   tipc: recode gets...
1677
1678
  	if (res)
  		return res;	/* "get" failed */
b97bf3fd8   Per Liden   [TIPC] Initial merge
1679

25860c3bd   Paul Gortmaker   tipc: recode gets...
1680
1681
1682
1683
1684
1685
1686
  	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
1687
1688
1689
  }
  
  /**
b97bf3fd8   Per Liden   [TIPC] Initial merge
1690
1691
   * Protocol switches for the various types of TIPC sockets
   */
bca65eae3   Florian Westphal   [TIPC]: declare p...
1692
  static const struct proto_ops msg_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1693
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1694
1695
1696
1697
  	.family		= AF_TIPC,
  	.release	= release,
  	.bind		= bind,
  	.connect	= connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1698
  	.socketpair	= sock_no_socketpair,
245f3d342   Ying Xue   tipc: Simplify pr...
1699
  	.accept		= sock_no_accept,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1700
1701
  	.getname	= get_name,
  	.poll		= poll,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1702
  	.ioctl		= sock_no_ioctl,
245f3d342   Ying Xue   tipc: Simplify pr...
1703
  	.listen		= sock_no_listen,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1704
1705
1706
1707
1708
  	.shutdown	= shutdown,
  	.setsockopt	= setsockopt,
  	.getsockopt	= getsockopt,
  	.sendmsg	= send_msg,
  	.recvmsg	= recv_msg,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1709
1710
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
1711
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
1712
  static const struct proto_ops packet_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1713
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1714
1715
1716
1717
  	.family		= AF_TIPC,
  	.release	= release,
  	.bind		= bind,
  	.connect	= connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1718
  	.socketpair	= sock_no_socketpair,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1719
1720
1721
  	.accept		= accept,
  	.getname	= get_name,
  	.poll		= poll,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1722
  	.ioctl		= sock_no_ioctl,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1723
1724
1725
1726
1727
1728
  	.listen		= listen,
  	.shutdown	= shutdown,
  	.setsockopt	= setsockopt,
  	.getsockopt	= getsockopt,
  	.sendmsg	= send_packet,
  	.recvmsg	= recv_msg,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1729
1730
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
1731
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
1732
  static const struct proto_ops stream_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1733
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1734
1735
1736
1737
  	.family		= AF_TIPC,
  	.release	= release,
  	.bind		= bind,
  	.connect	= connect,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1738
  	.socketpair	= sock_no_socketpair,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1739
1740
1741
  	.accept		= accept,
  	.getname	= get_name,
  	.poll		= poll,
5eee6a6dc   Allan Stephens   [TIPC]: Use stand...
1742
  	.ioctl		= sock_no_ioctl,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1743
1744
1745
1746
1747
1748
  	.listen		= listen,
  	.shutdown	= shutdown,
  	.setsockopt	= setsockopt,
  	.getsockopt	= getsockopt,
  	.sendmsg	= send_stream,
  	.recvmsg	= recv_stream,
8238745a3   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1749
1750
  	.mmap		= sock_no_mmap,
  	.sendpage	= sock_no_sendpage
b97bf3fd8   Per Liden   [TIPC] Initial merge
1751
  };
bca65eae3   Florian Westphal   [TIPC]: declare p...
1752
  static const struct net_proto_family tipc_family_ops = {
0e65967e3   Allan Stephens   tipc: cleanup var...
1753
  	.owner		= THIS_MODULE,
b97bf3fd8   Per Liden   [TIPC] Initial merge
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
  	.family		= AF_TIPC,
  	.create		= tipc_create
  };
  
  static struct proto tipc_proto = {
  	.name		= "TIPC",
  	.owner		= THIS_MODULE,
  	.obj_size	= sizeof(struct tipc_sock)
  };
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
1765
   * tipc_socket_init - initialize TIPC socket interface
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1766
   *
b97bf3fd8   Per Liden   [TIPC] Initial merge
1767
1768
   * Returns 0 on success, errno otherwise
   */
4323add67   Per Liden   [TIPC] Avoid poll...
1769
  int tipc_socket_init(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1770
1771
  {
  	int res;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
1772
  	res = proto_register(&tipc_proto, 1);
b97bf3fd8   Per Liden   [TIPC] Initial merge
1773
  	if (res) {
d0a14a9db   Per Liden   [TIPC] Cleaned up...
1774
1775
  		err("Failed to register TIPC protocol type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
1776
1777
1778
1779
1780
  		goto out;
  	}
  
  	res = sock_register(&tipc_family_ops);
  	if (res) {
d0a14a9db   Per Liden   [TIPC] Cleaned up...
1781
1782
  		err("Failed to register TIPC socket type
  ");
b97bf3fd8   Per Liden   [TIPC] Initial merge
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
  		proto_unregister(&tipc_proto);
  		goto out;
  	}
  
  	sockets_enabled = 1;
   out:
  	return res;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
1793
   * tipc_socket_stop - stop TIPC socket interface
b97bf3fd8   Per Liden   [TIPC] Initial merge
1794
   */
0c3141e91   Allan Stephens   [TIPC]: Overhaul ...
1795

4323add67   Per Liden   [TIPC] Avoid poll...
1796
  void tipc_socket_stop(void)
b97bf3fd8   Per Liden   [TIPC] Initial merge
1797
1798
1799
1800
1801
1802
1803
1804
  {
  	if (!sockets_enabled)
  		return;
  
  	sockets_enabled = 0;
  	sock_unregister(tipc_family_ops.family);
  	proto_unregister(&tipc_proto);
  }