Blame view
net/tipc/socket.c
46 KB
b97bf3fd8 [TIPC] Initial merge |
1 2 |
/* * net/tipc/socket.c: TIPC socket API |
c43072852 [NET] TIPC: Fix w... |
3 |
* |
5eee6a6dc [TIPC]: Use stand... |
4 |
* Copyright (c) 2001-2007, Ericsson AB |
4132facae tipc: Remove unus... |
5 |
* Copyright (c) 2004-2008, 2010-2011, Wind River Systems |
b97bf3fd8 [TIPC] Initial merge |
6 7 |
* All rights reserved. * |
9ea1fd3c1 [TIPC] License he... |
8 |
* Redistribution and use in source and binary forms, with or without |
b97bf3fd8 [TIPC] Initial merge |
9 10 |
* modification, are permitted provided that the following conditions are met: * |
9ea1fd3c1 [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 [TIPC] Initial merge |
19 |
* |
9ea1fd3c1 [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 [TIPC] Initial merge |
34 35 |
* POSSIBILITY OF SUCH DAMAGE. */ |
bc3b2d7fb net: Add export.h... |
36 |
#include <linux/export.h> |
b97bf3fd8 [TIPC] Initial merge |
37 |
#include <net/sock.h> |
b97bf3fd8 [TIPC] Initial merge |
38 |
#include "core.h" |
d265fef6d tipc: Remove obso... |
39 |
#include "port.h" |
b97bf3fd8 [TIPC] Initial merge |
40 41 42 |
#define SS_LISTENING -1 /* socket is listening */ #define SS_READY -2 /* socket is connectionless */ |
3654ea02f [TIPC]: Improve s... |
43 44 |
#define OVERLOAD_LIMIT_BASE 5000 #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ |
b97bf3fd8 [TIPC] Initial merge |
45 46 47 48 |
struct tipc_sock { struct sock sk; struct tipc_port *p; |
2da59918e tipc: Fix race co... |
49 |
struct tipc_portid peer_name; |
a0f40f02e tipc: Prevent rou... |
50 |
unsigned int conn_timeout; |
b97bf3fd8 [TIPC] Initial merge |
51 |
}; |
0c3141e91 [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 [TIPC] Initial merge |
54 |
|
71092ea12 tipc: Add support... |
55 56 |
#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \ (sock->state == SS_DISCONNECTING)) |
0c3141e91 [TIPC]: Overhaul ... |
57 |
static int backlog_rcv(struct sock *sk, struct sk_buff *skb); |
b97bf3fd8 [TIPC] Initial merge |
58 59 |
static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); static void wakeupdispatch(struct tipc_port *tport); |
bca65eae3 [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 [TIPC] Initial merge |
63 64 |
static struct proto tipc_proto; |
e3ec9c7d5 tipc: remove zero... |
65 |
static int sockets_enabled; |
b97bf3fd8 [TIPC] Initial merge |
66 67 |
static atomic_t tipc_queue_size = ATOMIC_INIT(0); |
c43072852 [NET] TIPC: Fix w... |
68 |
/* |
0c3141e91 [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 [TIPC] Initial merge |
117 |
*/ |
0c3141e91 [TIPC]: Overhaul ... |
118 119 |
static void advance_rx_queue(struct sock *sk) |
b97bf3fd8 [TIPC] Initial merge |
120 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
121 122 |
buf_discard(__skb_dequeue(&sk->sk_receive_queue)); atomic_dec(&tipc_queue_size); |
b97bf3fd8 [TIPC] Initial merge |
123 |
} |
0c3141e91 [TIPC]: Overhaul ... |
124 125 126 127 |
/** * discard_rx_queue - discard all buffers in socket receive queue * * Caller must hold socket lock |
b97bf3fd8 [TIPC] Initial merge |
128 |
*/ |
0c3141e91 [TIPC]: Overhaul ... |
129 130 |
static void discard_rx_queue(struct sock *sk) |
b97bf3fd8 [TIPC] Initial merge |
131 |
{ |
0c3141e91 [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 [TIPC] Initial merge |
138 139 140 |
} /** |
0c3141e91 [TIPC]: Overhaul ... |
141 142 143 |
* reject_rx_queue - reject all buffers in socket receive queue * * Caller must hold socket lock |
b97bf3fd8 [TIPC] Initial merge |
144 |
*/ |
0c3141e91 [TIPC]: Overhaul ... |
145 |
static void reject_rx_queue(struct sock *sk) |
b97bf3fd8 [TIPC] Initial merge |
146 |
{ |
0c3141e91 [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 [TIPC] Initial merge |
153 154 155 156 |
} /** * tipc_create - create a TIPC socket |
0c3141e91 [TIPC]: Overhaul ... |
157 |
* @net: network namespace (must be default network) |
b97bf3fd8 [TIPC] Initial merge |
158 159 |
* @sock: pre-allocated socket structure * @protocol: protocol indicator (must be 0) |
3f378b684 net: pass kern to... |
160 |
* @kern: caused by kernel or by userspace? |
c43072852 [NET] TIPC: Fix w... |
161 |
* |
0c3141e91 [TIPC]: Overhaul ... |
162 163 |
* This routine creates additional data structures used by the TIPC socket, * initializes them, and links them together. |
b97bf3fd8 [TIPC] Initial merge |
164 165 166 |
* * Returns 0 on success, errno otherwise */ |
0c3141e91 [TIPC]: Overhaul ... |
167 |
|
3f378b684 net: pass kern to... |
168 169 |
static int tipc_create(struct net *net, struct socket *sock, int protocol, int kern) |
b97bf3fd8 [TIPC] Initial merge |
170 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
171 172 |
const struct proto_ops *ops; socket_state state; |
b97bf3fd8 [TIPC] Initial merge |
173 |
struct sock *sk; |
7ef43ebaa tipc: Fix race co... |
174 |
struct tipc_port *tp_ptr; |
0c3141e91 [TIPC]: Overhaul ... |
175 176 |
/* Validate arguments */ |
b97bf3fd8 [TIPC] Initial merge |
177 |
|
b97bf3fd8 [TIPC] Initial merge |
178 179 |
if (unlikely(protocol != 0)) return -EPROTONOSUPPORT; |
b97bf3fd8 [TIPC] Initial merge |
180 181 |
switch (sock->type) { case SOCK_STREAM: |
0c3141e91 [TIPC]: Overhaul ... |
182 183 |
ops = &stream_ops; state = SS_UNCONNECTED; |
b97bf3fd8 [TIPC] Initial merge |
184 185 |
break; case SOCK_SEQPACKET: |
0c3141e91 [TIPC]: Overhaul ... |
186 187 |
ops = &packet_ops; state = SS_UNCONNECTED; |
b97bf3fd8 [TIPC] Initial merge |
188 189 |
break; case SOCK_DGRAM: |
b97bf3fd8 [TIPC] Initial merge |
190 |
case SOCK_RDM: |
0c3141e91 [TIPC]: Overhaul ... |
191 192 |
ops = &msg_ops; state = SS_READY; |
b97bf3fd8 [TIPC] Initial merge |
193 |
break; |
499786516 [TIPC]: Improved ... |
194 |
default: |
499786516 [TIPC]: Improved ... |
195 |
return -EPROTOTYPE; |
b97bf3fd8 [TIPC] Initial merge |
196 |
} |
0c3141e91 [TIPC]: Overhaul ... |
197 |
/* Allocate socket's protocol area */ |
6257ff217 [NET]: Forget the... |
198 |
sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto); |
0c3141e91 [TIPC]: Overhaul ... |
199 |
if (sk == NULL) |
b97bf3fd8 [TIPC] Initial merge |
200 |
return -ENOMEM; |
b97bf3fd8 [TIPC] Initial merge |
201 |
|
0c3141e91 [TIPC]: Overhaul ... |
202 |
/* Allocate TIPC port for socket to use */ |
b97bf3fd8 [TIPC] Initial merge |
203 |
|
0ea522416 tipc: Remove unne... |
204 205 206 |
tp_ptr = tipc_createport_raw(sk, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE); if (unlikely(!tp_ptr)) { |
0c3141e91 [TIPC]: Overhaul ... |
207 208 209 |
sk_free(sk); return -ENOMEM; } |
b97bf3fd8 [TIPC] Initial merge |
210 |
|
0c3141e91 [TIPC]: Overhaul ... |
211 |
/* Finish initializing socket data structures */ |
b97bf3fd8 [TIPC] Initial merge |
212 |
|
0c3141e91 [TIPC]: Overhaul ... |
213 214 |
sock->ops = ops; sock->state = state; |
b97bf3fd8 [TIPC] Initial merge |
215 |
|
0c3141e91 [TIPC]: Overhaul ... |
216 |
sock_init_data(sock, sk); |
0c3141e91 [TIPC]: Overhaul ... |
217 |
sk->sk_backlog_rcv = backlog_rcv; |
0ea522416 tipc: Remove unne... |
218 |
tipc_sk(sk)->p = tp_ptr; |
a0f40f02e tipc: Prevent rou... |
219 |
tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT; |
b97bf3fd8 [TIPC] Initial merge |
220 |
|
7ef43ebaa tipc: Fix race co... |
221 |
spin_unlock_bh(tp_ptr->lock); |
0c3141e91 [TIPC]: Overhaul ... |
222 |
if (sock->state == SS_READY) { |
0ea522416 tipc: Remove unne... |
223 |
tipc_set_portunreturnable(tp_ptr->ref, 1); |
0c3141e91 [TIPC]: Overhaul ... |
224 |
if (sock->type == SOCK_DGRAM) |
0ea522416 tipc: Remove unne... |
225 |
tipc_set_portunreliable(tp_ptr->ref, 1); |
0c3141e91 [TIPC]: Overhaul ... |
226 |
} |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
240 |
* |
b97bf3fd8 [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 [TIPC] Initial merge |
250 |
struct sock *sk = sock->sk; |
0c3141e91 [TIPC]: Overhaul ... |
251 |
struct tipc_port *tport; |
b97bf3fd8 [TIPC] Initial merge |
252 |
struct sk_buff *buf; |
0c3141e91 [TIPC]: Overhaul ... |
253 |
int res; |
b97bf3fd8 [TIPC] Initial merge |
254 |
|
0c3141e91 [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 [TIPC] Initial merge |
261 |
return 0; |
c43072852 [NET] TIPC: Fix w... |
262 |
|
0c3141e91 [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 [TIPC] Initial merge |
270 271 |
while (sock->state != SS_DISCONNECTING) { |
0c3141e91 [TIPC]: Overhaul ... |
272 273 |
buf = __skb_dequeue(&sk->sk_receive_queue); if (buf == NULL) |
b97bf3fd8 [TIPC] Initial merge |
274 |
break; |
0c3141e91 [TIPC]: Overhaul ... |
275 |
atomic_dec(&tipc_queue_size); |
0232fd0ac tipc: Allow recei... |
276 |
if (TIPC_SKB_CB(buf)->handle != 0) |
b97bf3fd8 [TIPC] Initial merge |
277 |
buf_discard(buf); |
0c3141e91 [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 [TIPC] Initial merge |
284 |
tipc_reject_msg(buf, TIPC_ERR_NO_PORT); |
0c3141e91 [TIPC]: Overhaul ... |
285 |
} |
b97bf3fd8 [TIPC] Initial merge |
286 |
} |
0c3141e91 [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 [TIPC] Initial merge |
291 |
|
0c3141e91 [TIPC]: Overhaul ... |
292 |
res = tipc_deleteport(tport->ref); |
b97bf3fd8 [TIPC] Initial merge |
293 |
|
0c3141e91 [TIPC]: Overhaul ... |
294 |
/* Discard any remaining (connection-based) messages in receive queue */ |
b97bf3fd8 [TIPC] Initial merge |
295 |
|
0c3141e91 [TIPC]: Overhaul ... |
296 |
discard_rx_queue(sk); |
b97bf3fd8 [TIPC] Initial merge |
297 |
|
0c3141e91 [TIPC]: Overhaul ... |
298 299 300 301 |
/* Reject any messages that accumulated in backlog queue */ sock->state = SS_DISCONNECTING; release_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
302 303 |
sock_put(sk); |
0c3141e91 [TIPC]: Overhaul ... |
304 |
sock->sk = NULL; |
b97bf3fd8 [TIPC] Initial merge |
305 |
|
b97bf3fd8 [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 [NET] TIPC: Fix w... |
314 |
* |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
318 |
* |
b97bf3fd8 [TIPC] Initial merge |
319 |
* Returns 0 on success, errno otherwise |
0c3141e91 [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 [TIPC] Initial merge |
323 324 325 326 |
*/ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) { |
b97bf3fd8 [TIPC] Initial merge |
327 |
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
0c3141e91 [TIPC]: Overhaul ... |
328 |
u32 portref = tipc_sk_port(sock->sk)->ref; |
b97bf3fd8 [TIPC] Initial merge |
329 |
|
0c3141e91 [TIPC]: Overhaul ... |
330 331 |
if (unlikely(!uaddr_len)) return tipc_withdraw(portref, 0, NULL); |
c43072852 [NET] TIPC: Fix w... |
332 |
|
0c3141e91 [TIPC]: Overhaul ... |
333 334 335 336 |
if (uaddr_len < sizeof(struct sockaddr_tipc)) return -EINVAL; if (addr->family != AF_TIPC) return -EAFNOSUPPORT; |
b97bf3fd8 [TIPC] Initial merge |
337 |
|
b97bf3fd8 [TIPC] Initial merge |
338 339 |
if (addr->addrtype == TIPC_ADDR_NAME) addr->addr.nameseq.upper = addr->addr.nameseq.lower; |
0c3141e91 [TIPC]: Overhaul ... |
340 341 |
else if (addr->addrtype != TIPC_ADDR_NAMESEQ) return -EAFNOSUPPORT; |
c43072852 [NET] TIPC: Fix w... |
342 |
|
0c3141e91 [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 [TIPC] Initial merge |
346 |
} |
c43072852 [NET] TIPC: Fix w... |
347 |
/** |
b97bf3fd8 [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 tipc: Fix race co... |
352 |
* @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID |
c43072852 [NET] TIPC: Fix w... |
353 |
* |
b97bf3fd8 [TIPC] Initial merge |
354 |
* Returns 0 on success, errno otherwise |
0c3141e91 [TIPC]: Overhaul ... |
355 |
* |
2da59918e 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 tipc: cleanup var... |
358 |
* a completely predictable manner). |
b97bf3fd8 [TIPC] Initial merge |
359 |
*/ |
c43072852 [NET] TIPC: Fix w... |
360 |
static int get_name(struct socket *sock, struct sockaddr *uaddr, |
b97bf3fd8 [TIPC] Initial merge |
361 362 |
int *uaddr_len, int peer) { |
b97bf3fd8 [TIPC] Initial merge |
363 |
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
2da59918e tipc: Fix race co... |
364 |
struct tipc_sock *tsock = tipc_sk(sock->sk); |
b97bf3fd8 [TIPC] Initial merge |
365 |
|
88f8a5e3e net: tipc: fix in... |
366 |
memset(addr, 0, sizeof(*addr)); |
0c3141e91 [TIPC]: Overhaul ... |
367 |
if (peer) { |
2da59918e 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 [TIPC]: Overhaul ... |
373 |
} else { |
b924dcf00 tipc: Delete tipc... |
374 375 |
addr->addr.id.ref = tsock->p->ref; addr->addr.id.node = tipc_own_addr; |
0c3141e91 [TIPC]: Overhaul ... |
376 |
} |
b97bf3fd8 [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 [TIPC] Initial merge |
382 |
addr->addr.name.domain = 0; |
0c3141e91 [TIPC]: Overhaul ... |
383 |
return 0; |
b97bf3fd8 [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 [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 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 [TIPC] Initial merge |
425 |
*/ |
c43072852 [NET] TIPC: Fix w... |
426 |
static unsigned int poll(struct file *file, struct socket *sock, |
b97bf3fd8 [TIPC] Initial merge |
427 428 |
poll_table *wait) { |
9b674e82b [TIPC]: Cosmetic ... |
429 |
struct sock *sk = sock->sk; |
f662c0705 tipc: correct pro... |
430 |
u32 mask = 0; |
9b674e82b [TIPC]: Cosmetic ... |
431 |
|
aa3951451 net: sk_sleep() h... |
432 |
poll_wait(file, sk_sleep(sk), wait); |
9b674e82b [TIPC]: Cosmetic ... |
433 |
|
f662c0705 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 [TIPC]: Cosmetic ... |
449 450 |
return mask; |
b97bf3fd8 [TIPC] Initial merge |
451 |
} |
c43072852 [NET] TIPC: Fix w... |
452 |
/** |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
456 |
* |
b97bf3fd8 [TIPC] Initial merge |
457 458 |
* Prevents restricted configuration commands from being issued by * unauthorized users. |
c43072852 [NET] TIPC: Fix w... |
459 |
* |
b97bf3fd8 [TIPC] Initial merge |
460 461 |
* Returns 0 if permission is granted, otherwise errno */ |
05790c645 [TIPC]: Remove in... |
462 |
static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) |
b97bf3fd8 [TIPC] Initial merge |
463 464 |
{ struct tipc_cfg_msg_hdr hdr; |
c43072852 [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 [NET] TIPC: Fix w... |
469 470 |
if (likely(dest->addr.name.name.type != TIPC_CFG_SRV)) return -EACCES; |
b97bf3fd8 [TIPC] Initial merge |
471 |
|
3f8dd9446 tipc: Prevent inv... |
472 473 |
if (!m->msg_iovlen || (m->msg_iov[0].iov_len < sizeof(hdr))) return -EMSGSIZE; |
c43072852 [NET] TIPC: Fix w... |
474 |
if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) |
b97bf3fd8 [TIPC] Initial merge |
475 |
return -EFAULT; |
70cb23477 [TIPC]: Fixed pri... |
476 |
if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN))) |
b97bf3fd8 [TIPC] Initial merge |
477 |
return -EACCES; |
c43072852 [NET] TIPC: Fix w... |
478 |
|
b97bf3fd8 [TIPC] Initial merge |
479 480 481 482 483 |
return 0; } /** * send_msg - send message in connectionless manner |
0c3141e91 [TIPC]: Overhaul ... |
484 |
* @iocb: if NULL, indicates that socket lock is already held |
b97bf3fd8 [TIPC] Initial merge |
485 486 |
* @sock: socket structure * @m: message to send |
e9024f0f7 [TIPC]: Non-opera... |
487 |
* @total_len: length of message |
c43072852 [NET] TIPC: Fix w... |
488 |
* |
b97bf3fd8 [TIPC] Initial merge |
489 |
* Message must have an destination specified explicitly. |
c43072852 [NET] TIPC: Fix w... |
490 |
* Used for SOCK_RDM and SOCK_DGRAM messages, |
b97bf3fd8 [TIPC] Initial merge |
491 492 |
* and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections. * (Note: 'SYN+' is prohibited on SOCK_STREAM.) |
c43072852 [NET] TIPC: Fix w... |
493 |
* |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
500 501 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
c43072852 [NET] TIPC: Fix w... |
502 |
struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; |
b97bf3fd8 [TIPC] Initial merge |
503 |
int needs_conn; |
1d835874a tipc: Add support... |
504 |
long timeout_val; |
b97bf3fd8 [TIPC] Initial merge |
505 506 507 508 |
int res = -EINVAL; if (unlikely(!dest)) return -EDESTADDRREQ; |
51f9cc1ff [TIPC]: Optimized... |
509 510 |
if (unlikely((m->msg_namelen < sizeof(*dest)) || (dest->family != AF_TIPC))) |
b97bf3fd8 [TIPC] Initial merge |
511 |
return -EINVAL; |
c29c3f70c tipc: Abort exces... |
512 513 514 |
if ((total_len > TIPC_MAX_USER_MSG_SIZE) || (m->msg_iovlen > (unsigned)INT_MAX)) return -EMSGSIZE; |
b97bf3fd8 [TIPC] Initial merge |
515 |
|
0c3141e91 [TIPC]: Overhaul ... |
516 517 |
if (iocb) lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
518 519 |
needs_conn = (sock->state != SS_READY); if (unlikely(needs_conn)) { |
0c3141e91 [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 [TIPC]: Implied c... |
533 |
if (dest->addrtype == TIPC_ADDR_NAME) { |
0c3141e91 [TIPC]: Overhaul ... |
534 535 |
tport->conn_type = dest->addr.name.name.type; tport->conn_instance = dest->addr.name.name.instance; |
3388007bc [TIPC]: Implied c... |
536 |
} |
b97bf3fd8 [TIPC] Initial merge |
537 538 |
/* Abort any pending connection attempts (very unlikely) */ |
0c3141e91 [TIPC]: Overhaul ... |
539 |
reject_rx_queue(sk); |
b97bf3fd8 [TIPC] Initial merge |
540 |
} |
1d835874a tipc: Add support... |
541 |
timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
c43072852 [NET] TIPC: Fix w... |
542 543 |
do { if (dest->addrtype == TIPC_ADDR_NAME) { |
2db9983a4 tipc: split varia... |
544 545 |
res = dest_name_check(dest, m); if (res) |
0c3141e91 [TIPC]: Overhaul ... |
546 547 |
break; res = tipc_send2name(tport->ref, |
c43072852 [NET] TIPC: Fix w... |
548 549 550 |
&dest->addr.name.name, dest->addr.name.domain, m->msg_iovlen, |
268969046 tipc: Avoid recom... |
551 552 |
m->msg_iov, total_len); |
0e65967e3 tipc: cleanup var... |
553 |
} else if (dest->addrtype == TIPC_ADDR_ID) { |
0c3141e91 [TIPC]: Overhaul ... |
554 |
res = tipc_send2port(tport->ref, |
c43072852 [NET] TIPC: Fix w... |
555 556 |
&dest->addr.id, m->msg_iovlen, |
268969046 tipc: Avoid recom... |
557 558 |
m->msg_iov, total_len); |
0e65967e3 tipc: cleanup var... |
559 |
} else if (dest->addrtype == TIPC_ADDR_MCAST) { |
b97bf3fd8 [TIPC] Initial merge |
560 561 |
if (needs_conn) { res = -EOPNOTSUPP; |
0c3141e91 [TIPC]: Overhaul ... |
562 |
break; |
b97bf3fd8 [TIPC] Initial merge |
563 |
} |
2db9983a4 tipc: split varia... |
564 565 |
res = dest_name_check(dest, m); if (res) |
0c3141e91 [TIPC]: Overhaul ... |
566 567 |
break; res = tipc_multicast(tport->ref, |
c43072852 [NET] TIPC: Fix w... |
568 |
&dest->addr.nameseq, |
c43072852 [NET] TIPC: Fix w... |
569 |
m->msg_iovlen, |
268969046 tipc: Avoid recom... |
570 571 |
m->msg_iov, total_len); |
c43072852 [NET] TIPC: Fix w... |
572 573 |
} if (likely(res != -ELINKCONG)) { |
a016892cd tipc: remove extr... |
574 |
if (needs_conn && (res >= 0)) |
0c3141e91 [TIPC]: Overhaul ... |
575 |
sock->state = SS_CONNECTING; |
0c3141e91 [TIPC]: Overhaul ... |
576 |
break; |
c43072852 [NET] TIPC: Fix w... |
577 |
} |
1d835874a tipc: Add support... |
578 579 |
if (timeout_val <= 0L) { res = timeout_val ? timeout_val : -EWOULDBLOCK; |
0c3141e91 [TIPC]: Overhaul ... |
580 |
break; |
c43072852 [NET] TIPC: Fix w... |
581 |
} |
0c3141e91 [TIPC]: Overhaul ... |
582 |
release_sock(sk); |
1d835874a tipc: Add support... |
583 584 |
timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), !tport->congested, timeout_val); |
0c3141e91 [TIPC]: Overhaul ... |
585 |
lock_sock(sk); |
c43072852 [NET] TIPC: Fix w... |
586 |
} while (1); |
0c3141e91 [TIPC]: Overhaul ... |
587 588 589 590 591 |
exit: if (iocb) release_sock(sk); return res; |
b97bf3fd8 [TIPC] Initial merge |
592 |
} |
c43072852 [NET] TIPC: Fix w... |
593 |
/** |
b97bf3fd8 [TIPC] Initial merge |
594 |
* send_packet - send a connection-oriented message |
0c3141e91 [TIPC]: Overhaul ... |
595 |
* @iocb: if NULL, indicates that socket lock is already held |
b97bf3fd8 [TIPC] Initial merge |
596 597 |
* @sock: socket structure * @m: message to send |
e9024f0f7 [TIPC]: Non-opera... |
598 |
* @total_len: length of message |
c43072852 [NET] TIPC: Fix w... |
599 |
* |
b97bf3fd8 [TIPC] Initial merge |
600 |
* Used for SOCK_SEQPACKET messages and SOCK_STREAM data. |
c43072852 [NET] TIPC: Fix w... |
601 |
* |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
608 609 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
c43072852 [NET] TIPC: Fix w... |
610 |
struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; |
1d835874a tipc: Add support... |
611 |
long timeout_val; |
b97bf3fd8 [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 tipc: Abort exces... |
618 619 620 |
if ((total_len > TIPC_MAX_USER_MSG_SIZE) || (m->msg_iovlen > (unsigned)INT_MAX)) return -EMSGSIZE; |
0c3141e91 [TIPC]: Overhaul ... |
621 622 |
if (iocb) lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
623 |
|
1d835874a tipc: Add support... |
624 |
timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
c43072852 [NET] TIPC: Fix w... |
625 |
do { |
bdd94789d [TIPC]: Connected... |
626 627 |
if (unlikely(sock->state != SS_CONNECTED)) { if (sock->state == SS_DISCONNECTING) |
c43072852 [NET] TIPC: Fix w... |
628 |
res = -EPIPE; |
bdd94789d [TIPC]: Connected... |
629 630 |
else res = -ENOTCONN; |
0c3141e91 [TIPC]: Overhaul ... |
631 |
break; |
bdd94789d [TIPC]: Connected... |
632 |
} |
268969046 tipc: Avoid recom... |
633 634 |
res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov, total_len); |
a016892cd tipc: remove extr... |
635 |
if (likely(res != -ELINKCONG)) |
0c3141e91 [TIPC]: Overhaul ... |
636 |
break; |
1d835874a tipc: Add support... |
637 638 |
if (timeout_val <= 0L) { res = timeout_val ? timeout_val : -EWOULDBLOCK; |
0c3141e91 [TIPC]: Overhaul ... |
639 |
break; |
c43072852 [NET] TIPC: Fix w... |
640 |
} |
0c3141e91 [TIPC]: Overhaul ... |
641 |
release_sock(sk); |
1d835874a tipc: Add support... |
642 643 |
timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), (!tport->congested || !tport->connected), timeout_val); |
0c3141e91 [TIPC]: Overhaul ... |
644 |
lock_sock(sk); |
c43072852 [NET] TIPC: Fix w... |
645 |
} while (1); |
0c3141e91 [TIPC]: Overhaul ... |
646 647 648 649 |
if (iocb) release_sock(sk); return res; |
b97bf3fd8 [TIPC] Initial merge |
650 |
} |
c43072852 [NET] TIPC: Fix w... |
651 |
/** |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
657 |
* |
b97bf3fd8 [TIPC] Initial merge |
658 |
* Used for SOCK_STREAM data. |
c43072852 [NET] TIPC: Fix w... |
659 660 |
* * Returns the number of bytes sent on success (or partial success), |
1303e8f17 [TIPC]: Stream so... |
661 |
* or errno if no data sent |
b97bf3fd8 [TIPC] Initial merge |
662 |
*/ |
b97bf3fd8 [TIPC] Initial merge |
663 664 665 |
static int send_stream(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { |
0c3141e91 [TIPC]: Overhaul ... |
666 667 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
b97bf3fd8 [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 [TIPC]: Optimize ... |
673 |
u32 hdr_size; |
b97bf3fd8 [TIPC] Initial merge |
674 675 |
int curr_left; int bytes_to_send; |
1303e8f17 [TIPC]: Stream so... |
676 |
int bytes_sent; |
b97bf3fd8 [TIPC] Initial merge |
677 |
int res; |
c43072852 [NET] TIPC: Fix w... |
678 |
|
0c3141e91 [TIPC]: Overhaul ... |
679 |
lock_sock(sk); |
05646c911 [TIPC]: Optimize ... |
680 |
/* Handle special cases where there is no connection */ |
b97bf3fd8 [TIPC] Initial merge |
681 |
|
c43072852 [NET] TIPC: Fix w... |
682 |
if (unlikely(sock->state != SS_CONNECTED)) { |
0c3141e91 [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 [NET] TIPC: Fix w... |
693 |
} |
b97bf3fd8 [TIPC] Initial merge |
694 |
|
0c3141e91 [TIPC]: Overhaul ... |
695 696 697 698 |
if (unlikely(m->msg_name)) { res = -EISCONN; goto exit; } |
eb5959c2b [TIPC]: Stream so... |
699 |
|
c29c3f70c 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 [NET] TIPC: Fix w... |
705 |
/* |
b97bf3fd8 [TIPC] Initial merge |
706 707 |
* Send each iovec entry using one or more messages * |
c43072852 [NET] TIPC: Fix w... |
708 |
* Note: This algorithm is good for the most likely case |
b97bf3fd8 [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 [TIPC]: Stream so... |
712 713 |
curr_iov = m->msg_iov; curr_iovlen = m->msg_iovlen; |
b97bf3fd8 [TIPC] Initial merge |
714 715 |
my_msg.msg_iov = &my_iov; my_msg.msg_iovlen = 1; |
eb5959c2b [TIPC]: Stream so... |
716 717 |
my_msg.msg_flags = m->msg_flags; my_msg.msg_name = NULL; |
1303e8f17 [TIPC]: Stream so... |
718 |
bytes_sent = 0; |
b97bf3fd8 [TIPC] Initial merge |
719 |
|
05646c911 [TIPC]: Optimize ... |
720 |
hdr_size = msg_hdr_sz(&tport->phdr); |
b97bf3fd8 [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 [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 [TIPC] Initial merge |
731 732 |
my_iov.iov_base = curr_start; my_iov.iov_len = bytes_to_send; |
268969046 tipc: Avoid recom... |
733 |
res = send_packet(NULL, sock, &my_msg, bytes_to_send); |
2db9983a4 tipc: split varia... |
734 |
if (res < 0) { |
0c3141e91 [TIPC]: Overhaul ... |
735 |
if (bytes_sent) |
05646c911 [TIPC]: Optimize ... |
736 |
res = bytes_sent; |
0c3141e91 [TIPC]: Overhaul ... |
737 |
goto exit; |
1303e8f17 [TIPC]: Stream so... |
738 |
} |
b97bf3fd8 [TIPC] Initial merge |
739 740 |
curr_left -= bytes_to_send; curr_start += bytes_to_send; |
1303e8f17 [TIPC]: Stream so... |
741 |
bytes_sent += bytes_to_send; |
b97bf3fd8 [TIPC] Initial merge |
742 743 744 745 |
} curr_iov++; } |
0c3141e91 [TIPC]: Overhaul ... |
746 747 748 749 |
res = bytes_sent; exit: release_sock(sk); return res; |
b97bf3fd8 [TIPC] Initial merge |
750 751 752 753 754 |
} /** * auto_connect - complete connection setup to a remote port * @sock: socket structure |
b97bf3fd8 [TIPC] Initial merge |
755 |
* @msg: peer's response message |
c43072852 [NET] TIPC: Fix w... |
756 |
* |
b97bf3fd8 [TIPC] Initial merge |
757 758 |
* Returns 0 on success, errno otherwise */ |
0c3141e91 [TIPC]: Overhaul ... |
759 |
static int auto_connect(struct socket *sock, struct tipc_msg *msg) |
b97bf3fd8 [TIPC] Initial merge |
760 |
{ |
2da59918e tipc: Fix race co... |
761 |
struct tipc_sock *tsock = tipc_sk(sock->sk); |
b97bf3fd8 [TIPC] Initial merge |
762 763 764 765 766 |
if (msg_errcode(msg)) { sock->state = SS_DISCONNECTING; return -ECONNREFUSED; } |
2da59918e 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 [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 [NET] TIPC: Fix w... |
779 |
* |
b97bf3fd8 [TIPC] Initial merge |
780 781 |
* Note: Address is not captured if not requested by receiver. */ |
05790c645 [TIPC]: Remove in... |
782 |
static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) |
b97bf3fd8 [TIPC] Initial merge |
783 |
{ |
c43072852 [NET] TIPC: Fix w... |
784 |
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; |
b97bf3fd8 [TIPC] Initial merge |
785 |
|
c43072852 [NET] TIPC: Fix w... |
786 |
if (addr) { |
b97bf3fd8 [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 tipc: cleanup var... |
791 792 |
addr->addr.name.domain = 0; /* could leave uninitialized */ addr->scope = 0; /* could leave uninitialized */ |
b97bf3fd8 [TIPC] Initial merge |
793 794 795 796 797 |
m->msg_namelen = sizeof(struct sockaddr_tipc); } } /** |
c43072852 [NET] TIPC: Fix w... |
798 |
* anc_data_recv - optionally capture ancillary data for received message |
b97bf3fd8 [TIPC] Initial merge |
799 800 801 |
* @m: descriptor for message info * @msg: received message header * @tport: TIPC port associated with message |
c43072852 [NET] TIPC: Fix w... |
802 |
* |
b97bf3fd8 [TIPC] Initial merge |
803 |
* Note: Ancillary data is not captured if not requested by receiver. |
c43072852 [NET] TIPC: Fix w... |
804 |
* |
b97bf3fd8 [TIPC] Initial merge |
805 806 |
* Returns 0 if successful, otherwise errno */ |
05790c645 [TIPC]: Remove in... |
807 |
static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, |
b97bf3fd8 [TIPC] Initial merge |
808 809 810 811 812 |
struct tipc_port *tport) { u32 anc_data[3]; u32 err; u32 dest_type; |
3546c7508 [TIPC]: Can now r... |
813 |
int has_name; |
b97bf3fd8 [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 tipc: split varia... |
825 826 |
res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data); if (res) |
b97bf3fd8 [TIPC] Initial merge |
827 |
return res; |
2db9983a4 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 [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 [TIPC]: Can now r... |
841 |
has_name = 1; |
b97bf3fd8 [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 [TIPC]: Can now r... |
847 |
has_name = 1; |
b97bf3fd8 [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 [TIPC]: Can now r... |
853 |
has_name = (tport->conn_type != 0); |
b97bf3fd8 [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 [TIPC]: Can now r... |
859 |
has_name = 0; |
b97bf3fd8 [TIPC] Initial merge |
860 |
} |
2db9983a4 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 [TIPC] Initial merge |
866 867 868 |
return 0; } |
c43072852 [NET] TIPC: Fix w... |
869 |
/** |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
875 |
* |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
885 886 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
b97bf3fd8 [TIPC] Initial merge |
887 888 |
struct sk_buff *buf; struct tipc_msg *msg; |
71092ea12 tipc: Add support... |
889 |
long timeout; |
b97bf3fd8 [TIPC] Initial merge |
890 891 892 |
unsigned int sz; u32 err; int res; |
0c3141e91 [TIPC]: Overhaul ... |
893 |
/* Catch invalid receive requests */ |
b97bf3fd8 [TIPC] Initial merge |
894 |
|
b97bf3fd8 [TIPC] Initial merge |
895 896 |
if (unlikely(!buf_len)) return -EINVAL; |
0c3141e91 [TIPC]: Overhaul ... |
897 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
898 |
|
0c3141e91 [TIPC]: Overhaul ... |
899 900 |
if (unlikely(sock->state == SS_UNCONNECTED)) { res = -ENOTCONN; |
b97bf3fd8 [TIPC] Initial merge |
901 902 |
goto exit; } |
71092ea12 tipc: Add support... |
903 |
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
0c3141e91 [TIPC]: Overhaul ... |
904 |
restart: |
b97bf3fd8 [TIPC] Initial merge |
905 |
|
0c3141e91 [TIPC]: Overhaul ... |
906 |
/* Look for a message in receive queue; wait if necessary */ |
b97bf3fd8 [TIPC] Initial merge |
907 |
|
0c3141e91 [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 tipc: Add support... |
913 914 |
if (timeout <= 0L) { res = timeout ? timeout : -EWOULDBLOCK; |
0c3141e91 [TIPC]: Overhaul ... |
915 916 917 |
goto exit; } release_sock(sk); |
71092ea12 tipc: Add support... |
918 919 920 |
timeout = wait_event_interruptible_timeout(*sk_sleep(sk), tipc_rx_ready(sock), timeout); |
0c3141e91 [TIPC]: Overhaul ... |
921 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
922 |
} |
0c3141e91 [TIPC]: Overhaul ... |
923 |
/* Look at first message in receive queue */ |
b97bf3fd8 [TIPC] Initial merge |
924 |
|
0c3141e91 [TIPC]: Overhaul ... |
925 |
buf = skb_peek(&sk->sk_receive_queue); |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
933 934 |
res = auto_connect(sock, msg); if (res) |
b97bf3fd8 [TIPC] Initial merge |
935 936 937 938 939 940 |
goto exit; } /* Discard an empty non-errored message & try again */ if ((!sz) && (!err)) { |
0c3141e91 [TIPC]: Overhaul ... |
941 |
advance_rx_queue(sk); |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
950 951 |
res = anc_data_recv(m, msg, tport); if (res) |
b97bf3fd8 [TIPC] Initial merge |
952 953 954 |
goto exit; /* Capture message data (if valid) & compute return value (always) */ |
c43072852 [NET] TIPC: Fix w... |
955 |
|
b97bf3fd8 [TIPC] Initial merge |
956 957 958 959 960 |
if (!err) { if (unlikely(buf_len < sz)) { sz = buf_len; m->msg_flags |= MSG_TRUNC; } |
0232fd0ac tipc: Allow recei... |
961 962 963 |
res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg), m->msg_iov, sz); if (res) |
b97bf3fd8 [TIPC] Initial merge |
964 |
goto exit; |
b97bf3fd8 [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 [TIPC]: Skip conn... |
977 |
if ((sock->state != SS_READY) && |
0c3141e91 [TIPC]: Overhaul ... |
978 979 980 |
(++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) tipc_acknowledge(tport->ref, tport->conn_unacked); advance_rx_queue(sk); |
c43072852 [NET] TIPC: Fix w... |
981 |
} |
b97bf3fd8 [TIPC] Initial merge |
982 |
exit: |
0c3141e91 [TIPC]: Overhaul ... |
983 |
release_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
984 985 |
return res; } |
c43072852 [NET] TIPC: Fix w... |
986 |
/** |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
992 993 |
* * Used for SOCK_STREAM messages only. If not enough data is available |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
1002 1003 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
b97bf3fd8 [TIPC] Initial merge |
1004 1005 |
struct sk_buff *buf; struct tipc_msg *msg; |
71092ea12 tipc: Add support... |
1006 |
long timeout; |
b97bf3fd8 [TIPC] Initial merge |
1007 |
unsigned int sz; |
3720d40b2 tipc: add SO_RCVL... |
1008 |
int sz_to_copy, target, needed; |
b97bf3fd8 [TIPC] Initial merge |
1009 |
int sz_copied = 0; |
b97bf3fd8 [TIPC] Initial merge |
1010 |
u32 err; |
0c3141e91 [TIPC]: Overhaul ... |
1011 |
int res = 0; |
b97bf3fd8 [TIPC] Initial merge |
1012 |
|
0c3141e91 [TIPC]: Overhaul ... |
1013 |
/* Catch invalid receive attempts */ |
b97bf3fd8 [TIPC] Initial merge |
1014 |
|
b97bf3fd8 [TIPC] Initial merge |
1015 1016 |
if (unlikely(!buf_len)) return -EINVAL; |
0c3141e91 [TIPC]: Overhaul ... |
1017 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1018 |
|
0c3141e91 [TIPC]: Overhaul ... |
1019 1020 1021 |
if (unlikely((sock->state == SS_UNCONNECTED) || (sock->state == SS_CONNECTING))) { res = -ENOTCONN; |
b97bf3fd8 [TIPC] Initial merge |
1022 1023 |
goto exit; } |
3720d40b2 tipc: add SO_RCVL... |
1024 |
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); |
71092ea12 tipc: Add support... |
1025 |
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
0c3141e91 [TIPC]: Overhaul ... |
1026 |
restart: |
b97bf3fd8 [TIPC] Initial merge |
1027 |
|
0c3141e91 [TIPC]: Overhaul ... |
1028 |
/* Look for a message in receive queue; wait if necessary */ |
b97bf3fd8 [TIPC] Initial merge |
1029 |
|
0c3141e91 [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 tipc: Add support... |
1035 1036 |
if (timeout <= 0L) { res = timeout ? timeout : -EWOULDBLOCK; |
0c3141e91 [TIPC]: Overhaul ... |
1037 1038 1039 |
goto exit; } release_sock(sk); |
71092ea12 tipc: Add support... |
1040 1041 1042 |
timeout = wait_event_interruptible_timeout(*sk_sleep(sk), tipc_rx_ready(sock), timeout); |
0c3141e91 [TIPC]: Overhaul ... |
1043 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1044 |
} |
0c3141e91 [TIPC]: Overhaul ... |
1045 |
/* Look at first message in receive queue */ |
b97bf3fd8 [TIPC] Initial merge |
1046 |
|
0c3141e91 [TIPC]: Overhaul ... |
1047 |
buf = skb_peek(&sk->sk_receive_queue); |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
1055 |
advance_rx_queue(sk); |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
1063 1064 |
res = anc_data_recv(m, msg, tport); if (res) |
b97bf3fd8 [TIPC] Initial merge |
1065 1066 1067 1068 |
goto exit; } /* Capture message data (if valid) & compute return value (always) */ |
c43072852 [NET] TIPC: Fix w... |
1069 |
|
b97bf3fd8 [TIPC] Initial merge |
1070 |
if (!err) { |
0232fd0ac tipc: Allow recei... |
1071 |
u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle); |
b97bf3fd8 [TIPC] Initial merge |
1072 |
|
0232fd0ac tipc: Allow recei... |
1073 |
sz -= offset; |
b97bf3fd8 [TIPC] Initial merge |
1074 1075 |
needed = (buf_len - sz_copied); sz_to_copy = (sz <= needed) ? sz : needed; |
0232fd0ac 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 [TIPC] Initial merge |
1080 |
goto exit; |
0232fd0ac tipc: Allow recei... |
1081 |
|
b97bf3fd8 [TIPC] Initial merge |
1082 1083 1084 1085 |
sz_copied += sz_to_copy; if (sz_to_copy < sz) { if (!(flags & MSG_PEEK)) |
0232fd0ac tipc: Allow recei... |
1086 1087 |
TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)(offset + sz_to_copy); |
b97bf3fd8 [TIPC] Initial merge |
1088 1089 |
goto exit; } |
b97bf3fd8 [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 [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 [NET] TIPC: Fix w... |
1106 |
} |
b97bf3fd8 [TIPC] Initial merge |
1107 1108 |
/* Loop around if more data is required */ |
f64f9e719 net: Move && and ... |
1109 1110 |
if ((sz_copied < buf_len) && /* didn't get all requested data */ (!skb_queue_empty(&sk->sk_receive_queue) || |
3720d40b2 tipc: add SO_RCVL... |
1111 |
(sz_copied < target)) && /* and more is ready or required */ |
f64f9e719 net: Move && and ... |
1112 1113 |
(!(flags & MSG_PEEK)) && /* and aren't just peeking at data */ (!err)) /* and haven't reached a FIN */ |
b97bf3fd8 [TIPC] Initial merge |
1114 1115 1116 |
goto restart; exit: |
0c3141e91 [TIPC]: Overhaul ... |
1117 |
release_sock(sk); |
a3b0a5a9d [TIPC]: Simplify ... |
1118 |
return sz_copied ? sz_copied : res; |
b97bf3fd8 [TIPC] Initial merge |
1119 1120 1121 |
} /** |
1819b8371 [TIPC]: Correct "... |
1122 1123 |
* rx_queue_full - determine if receive queue can accept another message * @msg: message to be added to queue |
b97bf3fd8 [TIPC] Initial merge |
1124 1125 |
* @queue_size: current size of queue * @base: nominal maximum size of queue |
c43072852 [NET] TIPC: Fix w... |
1126 |
* |
1819b8371 [TIPC]: Correct "... |
1127 |
* Returns 1 if queue is unable to accept message, 0 otherwise |
b97bf3fd8 [TIPC] Initial merge |
1128 |
*/ |
1819b8371 [TIPC]: Correct "... |
1129 |
static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base) |
b97bf3fd8 [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 net: return opera... |
1145 |
return queue_size >= threshold; |
b97bf3fd8 [TIPC] Initial merge |
1146 |
} |
c43072852 [NET] TIPC: Fix w... |
1147 |
/** |
0c3141e91 [TIPC]: Overhaul ... |
1148 1149 |
* filter_rcv - validate incoming message * @sk: socket |
b97bf3fd8 [TIPC] Initial merge |
1150 |
* @buf: message |
c43072852 [NET] TIPC: Fix w... |
1151 |
* |
0c3141e91 [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 [NET] TIPC: Fix w... |
1156 |
* |
b97bf3fd8 [TIPC] Initial merge |
1157 1158 |
* Returns TIPC error status code (TIPC_OK if message is not to be rejected) */ |
0c3141e91 [TIPC]: Overhaul ... |
1159 |
static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) |
b97bf3fd8 [TIPC] Initial merge |
1160 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1161 |
struct socket *sock = sk->sk_socket; |
b97bf3fd8 [TIPC] Initial merge |
1162 |
struct tipc_msg *msg = buf_msg(buf); |
b97bf3fd8 [TIPC] Initial merge |
1163 |
u32 recv_q_len; |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
1171 |
|
b97bf3fd8 [TIPC] Initial merge |
1172 |
if (sock->state == SS_READY) { |
b29f14284 tipc: remove call... |
1173 |
if (msg_connected(msg)) |
b97bf3fd8 [TIPC] Initial merge |
1174 |
return TIPC_ERR_NO_PORT; |
b97bf3fd8 [TIPC] Initial merge |
1175 |
} else { |
b29f14284 tipc: remove call... |
1176 |
if (msg_mcast(msg)) |
b97bf3fd8 [TIPC] Initial merge |
1177 |
return TIPC_ERR_NO_PORT; |
b97bf3fd8 [TIPC] Initial merge |
1178 |
if (sock->state == SS_CONNECTED) { |
b29f14284 tipc: remove call... |
1179 |
if (!msg_connected(msg)) |
b97bf3fd8 [TIPC] Initial merge |
1180 |
return TIPC_ERR_NO_PORT; |
b29f14284 tipc: remove call... |
1181 1182 |
} else if (sock->state == SS_CONNECTING) { if (!msg_connected(msg) && (msg_errcode(msg) == 0)) |
b97bf3fd8 [TIPC] Initial merge |
1183 |
return TIPC_ERR_NO_PORT; |
b29f14284 tipc: remove call... |
1184 1185 |
} else if (sock->state == SS_LISTENING) { if (msg_connected(msg) || msg_errcode(msg)) |
b97bf3fd8 [TIPC] Initial merge |
1186 |
return TIPC_ERR_NO_PORT; |
b29f14284 tipc: remove call... |
1187 |
} else if (sock->state == SS_DISCONNECTING) { |
b97bf3fd8 [TIPC] Initial merge |
1188 |
return TIPC_ERR_NO_PORT; |
b29f14284 tipc: remove call... |
1189 1190 |
} else /* (sock->state == SS_UNCONNECTED) */ { if (msg_connected(msg) || msg_errcode(msg)) |
b97bf3fd8 [TIPC] Initial merge |
1191 |
return TIPC_ERR_NO_PORT; |
b97bf3fd8 [TIPC] Initial merge |
1192 1193 1194 1195 |
} } /* Reject message if there isn't room to queue it */ |
1819b8371 [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 [TIPC] Initial merge |
1199 |
return TIPC_ERR_OVERLOAD; |
c43072852 [NET] TIPC: Fix w... |
1200 |
} |
0c3141e91 [TIPC]: Overhaul ... |
1201 |
recv_q_len = skb_queue_len(&sk->sk_receive_queue); |
1819b8371 [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 [TIPC] Initial merge |
1204 |
return TIPC_ERR_OVERLOAD; |
c43072852 [NET] TIPC: Fix w... |
1205 |
} |
b97bf3fd8 [TIPC] Initial merge |
1206 |
|
0c3141e91 [TIPC]: Overhaul ... |
1207 |
/* Enqueue message (finally!) */ |
0232fd0ac tipc: Allow recei... |
1208 |
TIPC_SKB_CB(buf)->handle = 0; |
0c3141e91 [TIPC]: Overhaul ... |
1209 1210 |
atomic_inc(&tipc_queue_size); __skb_queue_tail(&sk->sk_receive_queue, buf); |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
1215 |
tipc_disconnect_port(tipc_sk_port(sk)); |
b97bf3fd8 [TIPC] Initial merge |
1216 |
} |
aa3951451 net: sk_sleep() h... |
1217 1218 |
if (waitqueue_active(sk_sleep(sk))) wake_up_interruptible(sk_sleep(sk)); |
0c3141e91 [TIPC]: Overhaul ... |
1219 1220 |
return TIPC_OK; } |
b97bf3fd8 [TIPC] Initial merge |
1221 |
|
0c3141e91 [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 [TIPC] Initial merge |
1231 |
|
0c3141e91 [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 net: backlog func... |
1268 |
if (sk_add_backlog(sk, buf)) |
53eecb1be tipc: use limited... |
1269 1270 1271 |
res = TIPC_ERR_OVERLOAD; else res = TIPC_OK; |
0c3141e91 [TIPC]: Overhaul ... |
1272 1273 1274 1275 |
} bh_unlock_sock(sk); return res; |
b97bf3fd8 [TIPC] Initial merge |
1276 |
} |
c43072852 [NET] TIPC: Fix w... |
1277 |
/** |
b97bf3fd8 [TIPC] Initial merge |
1278 1279 |
* wakeupdispatch - wake up port after congestion * @tport: port to wakeup |
c43072852 [NET] TIPC: Fix w... |
1280 |
* |
0c3141e91 [TIPC]: Overhaul ... |
1281 |
* Called with port lock already taken. |
b97bf3fd8 [TIPC] Initial merge |
1282 1283 1284 1285 |
*/ static void wakeupdispatch(struct tipc_port *tport) { |
0c3141e91 [TIPC]: Overhaul ... |
1286 |
struct sock *sk = (struct sock *)tport->usr_handle; |
b97bf3fd8 [TIPC] Initial merge |
1287 |
|
aa3951451 net: sk_sleep() h... |
1288 1289 |
if (waitqueue_active(sk_sleep(sk))) wake_up_interruptible(sk_sleep(sk)); |
b97bf3fd8 [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 [TIPC]: Overhaul ... |
1297 |
* @flags: file-related flags associated with socket |
b97bf3fd8 [TIPC] Initial merge |
1298 1299 1300 |
* * Returns 0 on success, errno otherwise */ |
c43072852 [NET] TIPC: Fix w... |
1301 |
static int connect(struct socket *sock, struct sockaddr *dest, int destlen, |
b97bf3fd8 [TIPC] Initial merge |
1302 1303 |
int flags) { |
0c3141e91 [TIPC]: Overhaul ... |
1304 |
struct sock *sk = sock->sk; |
b89741a0c [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 tipc: Prevent rou... |
1309 |
unsigned int timeout; |
b89741a0c [TIPC]: Cosmetic ... |
1310 |
int res; |
0c3141e91 [TIPC]: Overhaul ... |
1311 |
lock_sock(sk); |
b89741a0c [TIPC]: Cosmetic ... |
1312 |
/* For now, TIPC does not allow use of connect() with DGRAM/RDM types */ |
0c3141e91 [TIPC]: Overhaul ... |
1313 1314 1315 1316 |
if (sock->state == SS_READY) { res = -EOPNOTSUPP; goto exit; } |
b89741a0c [TIPC]: Cosmetic ... |
1317 1318 |
/* For now, TIPC does not support the non-blocking form of connect() */ |
0c3141e91 [TIPC]: Overhaul ... |
1319 |
if (flags & O_NONBLOCK) { |
35997e315 tipc: Provide cor... |
1320 |
res = -EOPNOTSUPP; |
0c3141e91 [TIPC]: Overhaul ... |
1321 1322 |
goto exit; } |
b89741a0c [TIPC]: Cosmetic ... |
1323 1324 |
/* Issue Posix-compliant error code if socket is in the wrong state */ |
0c3141e91 [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 [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 [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 [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 tipc: remove extr... |
1358 |
if (res < 0) |
0c3141e91 [TIPC]: Overhaul ... |
1359 |
goto exit; |
b89741a0c [TIPC]: Cosmetic ... |
1360 |
|
0c3141e91 [TIPC]: Overhaul ... |
1361 |
/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ |
b89741a0c [TIPC]: Cosmetic ... |
1362 |
|
564e83b51 tipc: Allow conne... |
1363 |
timeout = tipc_sk(sk)->conn_timeout; |
0c3141e91 [TIPC]: Overhaul ... |
1364 |
release_sock(sk); |
aa3951451 net: sk_sleep() h... |
1365 |
res = wait_event_interruptible_timeout(*sk_sleep(sk), |
0c3141e91 [TIPC]: Overhaul ... |
1366 1367 |
(!skb_queue_empty(&sk->sk_receive_queue) || (sock->state != SS_CONNECTING)), |
a0f40f02e tipc: Prevent rou... |
1368 1369 |
timeout ? (long)msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT); |
0c3141e91 [TIPC]: Overhaul ... |
1370 |
lock_sock(sk); |
b89741a0c [TIPC]: Cosmetic ... |
1371 |
|
b89741a0c [TIPC]: Cosmetic ... |
1372 |
if (res > 0) { |
0c3141e91 [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 tipc: remove extr... |
1382 |
if (sock->state == SS_CONNECTED) |
0c3141e91 [TIPC]: Overhaul ... |
1383 |
res = -EISCONN; |
a016892cd tipc: remove extr... |
1384 |
else |
0c3141e91 [TIPC]: Overhaul ... |
1385 |
res = -ECONNREFUSED; |
b89741a0c [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 [TIPC]: Overhaul ... |
1394 1395 |
exit: release_sock(sk); |
b89741a0c [TIPC]: Cosmetic ... |
1396 |
return res; |
b97bf3fd8 [TIPC] Initial merge |
1397 |
} |
c43072852 [NET] TIPC: Fix w... |
1398 |
/** |
b97bf3fd8 [TIPC] Initial merge |
1399 1400 1401 |
* listen - allow socket to listen for incoming connections * @sock: socket structure * @len: (unused) |
c43072852 [NET] TIPC: Fix w... |
1402 |
* |
b97bf3fd8 [TIPC] Initial merge |
1403 1404 1405 1406 1407 |
* Returns 0 on success, errno otherwise */ static int listen(struct socket *sock, int len) { |
0c3141e91 [TIPC]: Overhaul ... |
1408 1409 1410 1411 |
struct sock *sk = sock->sk; int res; lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1412 |
|
245f3d342 tipc: Simplify pr... |
1413 |
if (sock->state != SS_UNCONNECTED) |
0c3141e91 [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 [TIPC] Initial merge |
1422 |
} |
c43072852 [NET] TIPC: Fix w... |
1423 |
/** |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
1428 |
* |
b97bf3fd8 [TIPC] Initial merge |
1429 1430 |
* Returns 0 on success, errno otherwise */ |
0c3141e91 [TIPC]: Overhaul ... |
1431 |
static int accept(struct socket *sock, struct socket *new_sock, int flags) |
b97bf3fd8 [TIPC] Initial merge |
1432 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1433 |
struct sock *sk = sock->sk; |
b97bf3fd8 [TIPC] Initial merge |
1434 |
struct sk_buff *buf; |
0c3141e91 [TIPC]: Overhaul ... |
1435 |
int res; |
b97bf3fd8 [TIPC] Initial merge |
1436 |
|
0c3141e91 [TIPC]: Overhaul ... |
1437 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1438 |
|
0c3141e91 [TIPC]: Overhaul ... |
1439 1440 |
if (sock->state != SS_LISTENING) { res = -EINVAL; |
b97bf3fd8 [TIPC] Initial merge |
1441 1442 |
goto exit; } |
b97bf3fd8 [TIPC] Initial merge |
1443 |
|
0c3141e91 [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 net: sk_sleep() h... |
1450 |
res = wait_event_interruptible(*sk_sleep(sk), |
0c3141e91 [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 net: pass kern to... |
1458 |
res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); |
b97bf3fd8 [TIPC] Initial merge |
1459 |
if (!res) { |
0c3141e91 [TIPC]: Overhaul ... |
1460 |
struct sock *new_sk = new_sock->sk; |
2da59918e tipc: Fix race co... |
1461 1462 |
struct tipc_sock *new_tsock = tipc_sk(new_sk); struct tipc_port *new_tport = new_tsock->p; |
0c3141e91 [TIPC]: Overhaul ... |
1463 |
u32 new_ref = new_tport->ref; |
b97bf3fd8 [TIPC] Initial merge |
1464 |
struct tipc_msg *msg = buf_msg(buf); |
0c3141e91 [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 [TIPC] Initial merge |
1476 |
|
2da59918e 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 [TIPC]: Overhaul ... |
1480 |
new_sock->state = SS_CONNECTED; |
b97bf3fd8 [TIPC] Initial merge |
1481 1482 1483 |
tipc_set_portimportance(new_ref, msg_importance(msg)); if (msg_named(msg)) { |
0c3141e91 [TIPC]: Overhaul ... |
1484 1485 |
new_tport->conn_type = msg_nametype(msg); new_tport->conn_instance = msg_nameinst(msg); |
b97bf3fd8 [TIPC] Initial merge |
1486 |
} |
0c3141e91 [TIPC]: Overhaul ... |
1487 |
/* |
b97bf3fd8 [TIPC] Initial merge |
1488 1489 1490 |
* Respond to 'SYN-' by discarding it & returning 'ACK'-. * Respond to 'SYN+' by queuing it on new socket. */ |
c43072852 [NET] TIPC: Fix w... |
1491 1492 |
if (!msg_data_sz(msg)) { struct msghdr m = {NULL,}; |
b97bf3fd8 [TIPC] Initial merge |
1493 |
|
0c3141e91 [TIPC]: Overhaul ... |
1494 1495 |
advance_rx_queue(sk); send_packet(NULL, new_sock, &m, 0); |
c43072852 [NET] TIPC: Fix w... |
1496 |
} else { |
0c3141e91 [TIPC]: Overhaul ... |
1497 1498 |
__skb_dequeue(&sk->sk_receive_queue); __skb_queue_head(&new_sk->sk_receive_queue, buf); |
b97bf3fd8 [TIPC] Initial merge |
1499 |
} |
0c3141e91 [TIPC]: Overhaul ... |
1500 |
release_sock(new_sk); |
b97bf3fd8 [TIPC] Initial merge |
1501 1502 |
} exit: |
0c3141e91 [TIPC]: Overhaul ... |
1503 |
release_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1504 1505 1506 1507 1508 1509 |
return res; } /** * shutdown - shutdown socket connection * @sock: socket structure |
e247a8f5d [TIPC]: Add argum... |
1510 |
* @how: direction to close (must be SHUT_RDWR) |
b97bf3fd8 [TIPC] Initial merge |
1511 1512 |
* * Terminates connection (if necessary), then purges socket's receive queue. |
c43072852 [NET] TIPC: Fix w... |
1513 |
* |
b97bf3fd8 [TIPC] Initial merge |
1514 1515 1516 1517 1518 |
* Returns 0 on success, errno otherwise */ static int shutdown(struct socket *sock, int how) { |
0c3141e91 [TIPC]: Overhaul ... |
1519 1520 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
b97bf3fd8 [TIPC] Initial merge |
1521 1522 |
struct sk_buff *buf; int res; |
e247a8f5d [TIPC]: Add argum... |
1523 1524 |
if (how != SHUT_RDWR) return -EINVAL; |
b97bf3fd8 [TIPC] Initial merge |
1525 |
|
0c3141e91 [TIPC]: Overhaul ... |
1526 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1527 1528 |
switch (sock->state) { |
0c3141e91 [TIPC]: Overhaul ... |
1529 |
case SS_CONNECTING: |
b97bf3fd8 [TIPC] Initial merge |
1530 |
case SS_CONNECTED: |
0c3141e91 [TIPC]: Overhaul ... |
1531 |
/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */ |
b97bf3fd8 [TIPC] Initial merge |
1532 |
restart: |
0c3141e91 [TIPC]: Overhaul ... |
1533 1534 |
buf = __skb_dequeue(&sk->sk_receive_queue); if (buf) { |
b97bf3fd8 [TIPC] Initial merge |
1535 |
atomic_dec(&tipc_queue_size); |
0232fd0ac tipc: Allow recei... |
1536 |
if (TIPC_SKB_CB(buf)->handle != 0) { |
b97bf3fd8 [TIPC] Initial merge |
1537 1538 1539 |
buf_discard(buf); goto restart; } |
0c3141e91 [TIPC]: Overhaul ... |
1540 |
tipc_disconnect(tport->ref); |
b97bf3fd8 [TIPC] Initial merge |
1541 |
tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN); |
0c3141e91 [TIPC]: Overhaul ... |
1542 1543 |
} else { tipc_shutdown(tport->ref); |
b97bf3fd8 [TIPC] Initial merge |
1544 |
} |
0c3141e91 [TIPC]: Overhaul ... |
1545 1546 |
sock->state = SS_DISCONNECTING; |
b97bf3fd8 [TIPC] Initial merge |
1547 1548 1549 1550 |
/* fall through */ case SS_DISCONNECTING: |
0c3141e91 [TIPC]: Overhaul ... |
1551 |
/* Discard any unreceived messages; wake up sleeping tasks */ |
b97bf3fd8 [TIPC] Initial merge |
1552 |
|
0c3141e91 [TIPC]: Overhaul ... |
1553 |
discard_rx_queue(sk); |
aa3951451 net: sk_sleep() h... |
1554 1555 |
if (waitqueue_active(sk_sleep(sk))) wake_up_interruptible(sk_sleep(sk)); |
b97bf3fd8 [TIPC] Initial merge |
1556 1557 1558 1559 1560 1561 |
res = 0; break; default: res = -ENOTCONN; } |
0c3141e91 [TIPC]: Overhaul ... |
1562 |
release_sock(sk); |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
1573 1574 |
* * For stream sockets only, accepts and ignores all IPPROTO_TCP options |
b97bf3fd8 [TIPC] Initial merge |
1575 |
* (to ease compatibility). |
c43072852 [NET] TIPC: Fix w... |
1576 |
* |
b97bf3fd8 [TIPC] Initial merge |
1577 1578 |
* Returns 0 on success, errno otherwise */ |
c43072852 [NET] TIPC: Fix w... |
1579 |
static int setsockopt(struct socket *sock, |
b7058842c net: Make setsock... |
1580 |
int lvl, int opt, char __user *ov, unsigned int ol) |
b97bf3fd8 [TIPC] Initial merge |
1581 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1582 1583 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
b97bf3fd8 [TIPC] Initial merge |
1584 1585 |
u32 value; int res; |
c43072852 [NET] TIPC: Fix w... |
1586 1587 |
if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) return 0; |
b97bf3fd8 [TIPC] Initial merge |
1588 1589 1590 1591 |
if (lvl != SOL_TIPC) return -ENOPROTOOPT; if (ol < sizeof(value)) return -EINVAL; |
2db9983a4 tipc: split varia... |
1592 1593 |
res = get_user(value, (u32 __user *)ov); if (res) |
b97bf3fd8 [TIPC] Initial merge |
1594 |
return res; |
0c3141e91 [TIPC]: Overhaul ... |
1595 |
lock_sock(sk); |
c43072852 [NET] TIPC: Fix w... |
1596 |
|
b97bf3fd8 [TIPC] Initial merge |
1597 1598 |
switch (opt) { case TIPC_IMPORTANCE: |
0c3141e91 [TIPC]: Overhaul ... |
1599 |
res = tipc_set_portimportance(tport->ref, value); |
b97bf3fd8 [TIPC] Initial merge |
1600 1601 1602 |
break; case TIPC_SRC_DROPPABLE: if (sock->type != SOCK_STREAM) |
0c3141e91 [TIPC]: Overhaul ... |
1603 |
res = tipc_set_portunreliable(tport->ref, value); |
c43072852 [NET] TIPC: Fix w... |
1604 |
else |
b97bf3fd8 [TIPC] Initial merge |
1605 1606 1607 |
res = -ENOPROTOOPT; break; case TIPC_DEST_DROPPABLE: |
0c3141e91 [TIPC]: Overhaul ... |
1608 |
res = tipc_set_portunreturnable(tport->ref, value); |
b97bf3fd8 [TIPC] Initial merge |
1609 1610 |
break; case TIPC_CONN_TIMEOUT: |
a0f40f02e tipc: Prevent rou... |
1611 |
tipc_sk(sk)->conn_timeout = value; |
0c3141e91 [TIPC]: Overhaul ... |
1612 |
/* no need to set "res", since already 0 at this point */ |
b97bf3fd8 [TIPC] Initial merge |
1613 1614 1615 1616 |
break; default: res = -EINVAL; } |
0c3141e91 [TIPC]: Overhaul ... |
1617 |
release_sock(sk); |
b97bf3fd8 [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 [NET] TIPC: Fix w... |
1628 1629 |
* * For stream sockets only, returns 0 length result for all IPPROTO_TCP options |
b97bf3fd8 [TIPC] Initial merge |
1630 |
* (to ease compatibility). |
c43072852 [NET] TIPC: Fix w... |
1631 |
* |
b97bf3fd8 [TIPC] Initial merge |
1632 1633 |
* Returns 0 on success, errno otherwise */ |
c43072852 [NET] TIPC: Fix w... |
1634 |
static int getsockopt(struct socket *sock, |
28c4dadd3 [PATCH] tipc __us... |
1635 |
int lvl, int opt, char __user *ov, int __user *ol) |
b97bf3fd8 [TIPC] Initial merge |
1636 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1637 1638 |
struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); |
c43072852 [NET] TIPC: Fix w... |
1639 |
int len; |
b97bf3fd8 [TIPC] Initial merge |
1640 |
u32 value; |
c43072852 [NET] TIPC: Fix w... |
1641 |
int res; |
b97bf3fd8 [TIPC] Initial merge |
1642 |
|
c43072852 [NET] TIPC: Fix w... |
1643 1644 |
if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) return put_user(0, ol); |
b97bf3fd8 [TIPC] Initial merge |
1645 1646 |
if (lvl != SOL_TIPC) return -ENOPROTOOPT; |
2db9983a4 tipc: split varia... |
1647 1648 |
res = get_user(len, ol); if (res) |
c43072852 [NET] TIPC: Fix w... |
1649 |
return res; |
b97bf3fd8 [TIPC] Initial merge |
1650 |
|
0c3141e91 [TIPC]: Overhaul ... |
1651 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1652 1653 1654 |
switch (opt) { case TIPC_IMPORTANCE: |
0c3141e91 [TIPC]: Overhaul ... |
1655 |
res = tipc_portimportance(tport->ref, &value); |
b97bf3fd8 [TIPC] Initial merge |
1656 1657 |
break; case TIPC_SRC_DROPPABLE: |
0c3141e91 [TIPC]: Overhaul ... |
1658 |
res = tipc_portunreliable(tport->ref, &value); |
b97bf3fd8 [TIPC] Initial merge |
1659 1660 |
break; case TIPC_DEST_DROPPABLE: |
0c3141e91 [TIPC]: Overhaul ... |
1661 |
res = tipc_portunreturnable(tport->ref, &value); |
b97bf3fd8 [TIPC] Initial merge |
1662 1663 |
break; case TIPC_CONN_TIMEOUT: |
a0f40f02e tipc: Prevent rou... |
1664 |
value = tipc_sk(sk)->conn_timeout; |
0c3141e91 [TIPC]: Overhaul ... |
1665 |
/* no need to set "res", since already 0 at this point */ |
b97bf3fd8 [TIPC] Initial merge |
1666 |
break; |
0e65967e3 tipc: cleanup var... |
1667 |
case TIPC_NODE_RECVQ_DEPTH: |
6650613d3 tipc: Add socket ... |
1668 1669 |
value = (u32)atomic_read(&tipc_queue_size); break; |
0e65967e3 tipc: cleanup var... |
1670 |
case TIPC_SOCK_RECVQ_DEPTH: |
6650613d3 tipc: Add socket ... |
1671 1672 |
value = skb_queue_len(&sk->sk_receive_queue); break; |
b97bf3fd8 [TIPC] Initial merge |
1673 1674 1675 |
default: res = -EINVAL; } |
0c3141e91 [TIPC]: Overhaul ... |
1676 |
release_sock(sk); |
25860c3bd tipc: recode gets... |
1677 1678 |
if (res) return res; /* "get" failed */ |
b97bf3fd8 [TIPC] Initial merge |
1679 |
|
25860c3bd 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 [TIPC] Initial merge |
1687 1688 1689 |
} /** |
b97bf3fd8 [TIPC] Initial merge |
1690 1691 |
* Protocol switches for the various types of TIPC sockets */ |
bca65eae3 [TIPC]: declare p... |
1692 |
static const struct proto_ops msg_ops = { |
0e65967e3 tipc: cleanup var... |
1693 |
.owner = THIS_MODULE, |
b97bf3fd8 [TIPC] Initial merge |
1694 1695 1696 1697 |
.family = AF_TIPC, .release = release, .bind = bind, .connect = connect, |
5eee6a6dc [TIPC]: Use stand... |
1698 |
.socketpair = sock_no_socketpair, |
245f3d342 tipc: Simplify pr... |
1699 |
.accept = sock_no_accept, |
b97bf3fd8 [TIPC] Initial merge |
1700 1701 |
.getname = get_name, .poll = poll, |
5eee6a6dc [TIPC]: Use stand... |
1702 |
.ioctl = sock_no_ioctl, |
245f3d342 tipc: Simplify pr... |
1703 |
.listen = sock_no_listen, |
b97bf3fd8 [TIPC] Initial merge |
1704 1705 1706 1707 1708 |
.shutdown = shutdown, .setsockopt = setsockopt, .getsockopt = getsockopt, .sendmsg = send_msg, .recvmsg = recv_msg, |
8238745a3 [NET] TIPC: Fix w... |
1709 1710 |
.mmap = sock_no_mmap, .sendpage = sock_no_sendpage |
b97bf3fd8 [TIPC] Initial merge |
1711 |
}; |
bca65eae3 [TIPC]: declare p... |
1712 |
static const struct proto_ops packet_ops = { |
0e65967e3 tipc: cleanup var... |
1713 |
.owner = THIS_MODULE, |
b97bf3fd8 [TIPC] Initial merge |
1714 1715 1716 1717 |
.family = AF_TIPC, .release = release, .bind = bind, .connect = connect, |
5eee6a6dc [TIPC]: Use stand... |
1718 |
.socketpair = sock_no_socketpair, |
b97bf3fd8 [TIPC] Initial merge |
1719 1720 1721 |
.accept = accept, .getname = get_name, .poll = poll, |
5eee6a6dc [TIPC]: Use stand... |
1722 |
.ioctl = sock_no_ioctl, |
b97bf3fd8 [TIPC] Initial merge |
1723 1724 1725 1726 1727 1728 |
.listen = listen, .shutdown = shutdown, .setsockopt = setsockopt, .getsockopt = getsockopt, .sendmsg = send_packet, .recvmsg = recv_msg, |
8238745a3 [NET] TIPC: Fix w... |
1729 1730 |
.mmap = sock_no_mmap, .sendpage = sock_no_sendpage |
b97bf3fd8 [TIPC] Initial merge |
1731 |
}; |
bca65eae3 [TIPC]: declare p... |
1732 |
static const struct proto_ops stream_ops = { |
0e65967e3 tipc: cleanup var... |
1733 |
.owner = THIS_MODULE, |
b97bf3fd8 [TIPC] Initial merge |
1734 1735 1736 1737 |
.family = AF_TIPC, .release = release, .bind = bind, .connect = connect, |
5eee6a6dc [TIPC]: Use stand... |
1738 |
.socketpair = sock_no_socketpair, |
b97bf3fd8 [TIPC] Initial merge |
1739 1740 1741 |
.accept = accept, .getname = get_name, .poll = poll, |
5eee6a6dc [TIPC]: Use stand... |
1742 |
.ioctl = sock_no_ioctl, |
b97bf3fd8 [TIPC] Initial merge |
1743 1744 1745 1746 1747 1748 |
.listen = listen, .shutdown = shutdown, .setsockopt = setsockopt, .getsockopt = getsockopt, .sendmsg = send_stream, .recvmsg = recv_stream, |
8238745a3 [NET] TIPC: Fix w... |
1749 1750 |
.mmap = sock_no_mmap, .sendpage = sock_no_sendpage |
b97bf3fd8 [TIPC] Initial merge |
1751 |
}; |
bca65eae3 [TIPC]: declare p... |
1752 |
static const struct net_proto_family tipc_family_ops = { |
0e65967e3 tipc: cleanup var... |
1753 |
.owner = THIS_MODULE, |
b97bf3fd8 [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 [TIPC] Avoid poll... |
1765 |
* tipc_socket_init - initialize TIPC socket interface |
c43072852 [NET] TIPC: Fix w... |
1766 |
* |
b97bf3fd8 [TIPC] Initial merge |
1767 1768 |
* Returns 0 on success, errno otherwise */ |
4323add67 [TIPC] Avoid poll... |
1769 |
int tipc_socket_init(void) |
b97bf3fd8 [TIPC] Initial merge |
1770 1771 |
{ int res; |
c43072852 [NET] TIPC: Fix w... |
1772 |
res = proto_register(&tipc_proto, 1); |
b97bf3fd8 [TIPC] Initial merge |
1773 |
if (res) { |
d0a14a9db [TIPC] Cleaned up... |
1774 1775 |
err("Failed to register TIPC protocol type "); |
b97bf3fd8 [TIPC] Initial merge |
1776 1777 1778 1779 1780 |
goto out; } res = sock_register(&tipc_family_ops); if (res) { |
d0a14a9db [TIPC] Cleaned up... |
1781 1782 |
err("Failed to register TIPC socket type "); |
b97bf3fd8 [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 [TIPC] Avoid poll... |
1793 |
* tipc_socket_stop - stop TIPC socket interface |
b97bf3fd8 [TIPC] Initial merge |
1794 |
*/ |
0c3141e91 [TIPC]: Overhaul ... |
1795 |
|
4323add67 [TIPC] Avoid poll... |
1796 |
void tipc_socket_stop(void) |
b97bf3fd8 [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); } |