Blame view
net/tipc/socket.c
73.5 KB
b97bf3fd8 [TIPC] Initial merge |
1 |
/* |
02c00c2ab tipc: fix potenti... |
2 |
* net/tipc/socket.c: TIPC socket API |
c43072852 [NET] TIPC: Fix w... |
3 |
* |
51b9a31c4 tipc: eliminate o... |
4 |
* Copyright (c) 2001-2007, 2012-2016, Ericsson AB |
c5fa7b3cf tipc: introduce n... |
5 |
* Copyright (c) 2004-2008, 2010-2013, 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. */ |
07f6c4bc0 tipc: convert tip... |
36 |
#include <linux/rhashtable.h> |
174cd4b1e sched/headers: Pr... |
37 |
#include <linux/sched/signal.h> |
b97bf3fd8 [TIPC] Initial merge |
38 |
#include "core.h" |
e2dafe87d tipc: RDM/DGRAM t... |
39 |
#include "name_table.h" |
78acb1f9b tipc: add ioctl t... |
40 |
#include "node.h" |
e2dafe87d tipc: RDM/DGRAM t... |
41 |
#include "link.h" |
c637c1035 tipc: resolve rac... |
42 |
#include "name_distr.h" |
2e84c60b7 tipc: remove incl... |
43 |
#include "socket.h" |
a6bf70f79 tipc: simplify in... |
44 |
#include "bcast.h" |
49cc66eae tipc: move netlin... |
45 |
#include "netlink.h" |
2cf8aa19f tipc: use standar... |
46 |
|
07f6c4bc0 tipc: convert tip... |
47 |
#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ |
2f55c4378 tipc: remove unne... |
48 |
#define CONN_PROBING_INTERVAL msecs_to_jiffies(3600000) /* [ms] => 1 h */ |
07f6c4bc0 tipc: convert tip... |
49 |
#define TIPC_FWD_MSG 1 |
07f6c4bc0 tipc: convert tip... |
50 51 |
#define TIPC_MAX_PORT 0xffffffff #define TIPC_MIN_PORT 1 |
e9f8b1010 tipc: refactor fu... |
52 |
#define TIPC_ACK_RATE 4 /* ACK at 1/4 of of rcv window size */ |
301bae56f tipc: merge struc... |
53 |
|
0c288c869 tipc: create TIPC... |
54 55 |
enum { TIPC_LISTEN = TCP_LISTEN, |
8ea642ee9 tipc: create TIPC... |
56 |
TIPC_ESTABLISHED = TCP_ESTABLISHED, |
438adcaf0 tipc: create TIPC... |
57 |
TIPC_OPEN = TCP_CLOSE, |
9fd4b070f tipc: create TIPC... |
58 |
TIPC_DISCONNECTING = TCP_CLOSE_WAIT, |
99a208898 tipc: create TIPC... |
59 |
TIPC_CONNECTING = TCP_SYN_SENT, |
0c288c869 tipc: create TIPC... |
60 |
}; |
301bae56f tipc: merge struc... |
61 62 63 |
/** * struct tipc_sock - TIPC socket structure * @sk: socket - interacts with 'port' and with user via the socket API |
301bae56f tipc: merge struc... |
64 65 66 67 |
* @conn_type: TIPC type used when connection was established * @conn_instance: TIPC instance used when connection was established * @published: non-zero if port has one or more associated names * @max_pkt: maximum packet size "hint" used when building messages sent by port |
07f6c4bc0 tipc: convert tip... |
68 |
* @portid: unique port identity in TIPC socket hash table |
301bae56f tipc: merge struc... |
69 |
* @phdr: preformatted message header used when sending messages |
365ad353c tipc: reduce risk... |
70 |
* #cong_links: list of congested links |
301bae56f tipc: merge struc... |
71 |
* @publications: list of publications for port |
365ad353c tipc: reduce risk... |
72 |
* @blocking_link: address of the congested link we are currently sleeping on |
301bae56f tipc: merge struc... |
73 74 |
* @pub_count: total # of publications port has made during its lifetime * @probing_state: |
301bae56f tipc: merge struc... |
75 76 |
* @conn_timeout: the time we can wait for an unresponded setup request * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue |
365ad353c tipc: reduce risk... |
77 |
* @cong_link_cnt: number of congested links |
301bae56f tipc: merge struc... |
78 79 |
* @sent_unacked: # messages sent by socket, and not yet acked by peer * @rcv_unacked: # messages read by user, but not yet acked back to peer |
aeda16b6a tipc: rename tsk-... |
80 |
* @peer: 'connected' peer for dgram/rdm |
07f6c4bc0 tipc: convert tip... |
81 |
* @node: hash table node |
01fd12bb1 tipc: make replic... |
82 |
* @mc_method: cookie for use between socket and broadcast layer |
07f6c4bc0 tipc: convert tip... |
83 |
* @rcu: rcu struct for tipc_sock |
301bae56f tipc: merge struc... |
84 85 86 |
*/ struct tipc_sock { struct sock sk; |
301bae56f tipc: merge struc... |
87 88 89 90 |
u32 conn_type; u32 conn_instance; int published; u32 max_pkt; |
07f6c4bc0 tipc: convert tip... |
91 |
u32 portid; |
301bae56f tipc: merge struc... |
92 |
struct tipc_msg phdr; |
365ad353c tipc: reduce risk... |
93 |
struct list_head cong_links; |
301bae56f tipc: merge struc... |
94 95 |
struct list_head publications; u32 pub_count; |
301bae56f tipc: merge struc... |
96 97 |
uint conn_timeout; atomic_t dupl_rcvcnt; |
8ea642ee9 tipc: create TIPC... |
98 |
bool probe_unacked; |
365ad353c tipc: reduce risk... |
99 |
u16 cong_link_cnt; |
10724cc7b tipc: redesign co... |
100 101 |
u16 snt_unacked; u16 snd_win; |
60020e185 tipc: propagate p... |
102 |
u16 peer_caps; |
10724cc7b tipc: redesign co... |
103 104 |
u16 rcv_unacked; u16 rcv_win; |
aeda16b6a tipc: rename tsk-... |
105 |
struct sockaddr_tipc peer; |
07f6c4bc0 tipc: convert tip... |
106 |
struct rhash_head node; |
01fd12bb1 tipc: make replic... |
107 |
struct tipc_mc_method mc_method; |
07f6c4bc0 tipc: convert tip... |
108 |
struct rcu_head rcu; |
301bae56f tipc: merge struc... |
109 |
}; |
b97bf3fd8 [TIPC] Initial merge |
110 |
|
4f4482dcd tipc: compensate ... |
111 |
static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb); |
676d23690 net: Fix use afte... |
112 |
static void tipc_data_ready(struct sock *sk); |
f288bef46 tipc: fix race/in... |
113 |
static void tipc_write_space(struct sock *sk); |
f4195d1ea tipc: avoid packe... |
114 |
static void tipc_sock_destruct(struct sock *sk); |
247f0f3c3 tipc: align tipc ... |
115 |
static int tipc_release(struct socket *sock); |
cdfbabfb2 net: Work around ... |
116 117 |
static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags, bool kern); |
f2f2a96a2 tipc: feed tipc s... |
118 |
static void tipc_sk_timeout(unsigned long data); |
301bae56f tipc: merge struc... |
119 |
static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, |
0fc87aaeb tipc: remove sour... |
120 |
struct tipc_name_seq const *seq); |
301bae56f tipc: merge struc... |
121 |
static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, |
0fc87aaeb tipc: remove sour... |
122 |
struct tipc_name_seq const *seq); |
e05b31f4b tipc: make tipc s... |
123 |
static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid); |
07f6c4bc0 tipc: convert tip... |
124 125 |
static int tipc_sk_insert(struct tipc_sock *tsk); static void tipc_sk_remove(struct tipc_sock *tsk); |
365ad353c tipc: reduce risk... |
126 |
static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dsz); |
39a0295f9 tipc: Don't use i... |
127 |
static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz); |
b97bf3fd8 [TIPC] Initial merge |
128 |
|
bca65eae3 [TIPC]: declare p... |
129 130 131 |
static const struct proto_ops packet_ops; static const struct proto_ops stream_ops; static const struct proto_ops msg_ops; |
b97bf3fd8 [TIPC] Initial merge |
132 |
static struct proto tipc_proto; |
6cca7289d tipc: Use inlined... |
133 |
static const struct rhashtable_params tsk_rht_params; |
c5898636c tipc: reduce usag... |
134 135 136 137 |
static u32 tsk_own_node(struct tipc_sock *tsk) { return msg_prevnode(&tsk->phdr); } |
301bae56f tipc: merge struc... |
138 |
static u32 tsk_peer_node(struct tipc_sock *tsk) |
2e84c60b7 tipc: remove incl... |
139 |
{ |
301bae56f tipc: merge struc... |
140 |
return msg_destnode(&tsk->phdr); |
2e84c60b7 tipc: remove incl... |
141 |
} |
301bae56f tipc: merge struc... |
142 |
static u32 tsk_peer_port(struct tipc_sock *tsk) |
2e84c60b7 tipc: remove incl... |
143 |
{ |
301bae56f tipc: merge struc... |
144 |
return msg_destport(&tsk->phdr); |
2e84c60b7 tipc: remove incl... |
145 |
} |
301bae56f tipc: merge struc... |
146 |
static bool tsk_unreliable(struct tipc_sock *tsk) |
2e84c60b7 tipc: remove incl... |
147 |
{ |
301bae56f tipc: merge struc... |
148 |
return msg_src_droppable(&tsk->phdr) != 0; |
2e84c60b7 tipc: remove incl... |
149 |
} |
301bae56f tipc: merge struc... |
150 |
static void tsk_set_unreliable(struct tipc_sock *tsk, bool unreliable) |
2e84c60b7 tipc: remove incl... |
151 |
{ |
301bae56f tipc: merge struc... |
152 |
msg_set_src_droppable(&tsk->phdr, unreliable ? 1 : 0); |
2e84c60b7 tipc: remove incl... |
153 |
} |
301bae56f tipc: merge struc... |
154 |
static bool tsk_unreturnable(struct tipc_sock *tsk) |
2e84c60b7 tipc: remove incl... |
155 |
{ |
301bae56f tipc: merge struc... |
156 |
return msg_dest_droppable(&tsk->phdr) != 0; |
2e84c60b7 tipc: remove incl... |
157 |
} |
301bae56f tipc: merge struc... |
158 |
static void tsk_set_unreturnable(struct tipc_sock *tsk, bool unreturnable) |
2e84c60b7 tipc: remove incl... |
159 |
{ |
301bae56f tipc: merge struc... |
160 |
msg_set_dest_droppable(&tsk->phdr, unreturnable ? 1 : 0); |
2e84c60b7 tipc: remove incl... |
161 |
} |
301bae56f tipc: merge struc... |
162 |
static int tsk_importance(struct tipc_sock *tsk) |
2e84c60b7 tipc: remove incl... |
163 |
{ |
301bae56f tipc: merge struc... |
164 |
return msg_importance(&tsk->phdr); |
2e84c60b7 tipc: remove incl... |
165 |
} |
301bae56f tipc: merge struc... |
166 |
static int tsk_set_importance(struct tipc_sock *tsk, int imp) |
2e84c60b7 tipc: remove incl... |
167 168 169 |
{ if (imp > TIPC_CRITICAL_IMPORTANCE) return -EINVAL; |
301bae56f tipc: merge struc... |
170 |
msg_set_importance(&tsk->phdr, (u32)imp); |
2e84c60b7 tipc: remove incl... |
171 172 |
return 0; } |
8826cde65 tipc: aggregate p... |
173 |
|
301bae56f tipc: merge struc... |
174 175 176 177 |
static struct tipc_sock *tipc_sk(const struct sock *sk) { return container_of(sk, struct tipc_sock, sk); } |
10724cc7b tipc: redesign co... |
178 |
static bool tsk_conn_cong(struct tipc_sock *tsk) |
301bae56f tipc: merge struc... |
179 |
{ |
6998cc6ec tipc: resolve con... |
180 |
return tsk->snt_unacked > tsk->snd_win; |
10724cc7b tipc: redesign co... |
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
} /* tsk_blocks(): translate a buffer size in bytes to number of * advertisable blocks, taking into account the ratio truesize(len)/len * We can trust that this ratio is always < 4 for len >= FLOWCTL_BLK_SZ */ static u16 tsk_adv_blocks(int len) { return len / FLOWCTL_BLK_SZ / 4; } /* tsk_inc(): increment counter for sent or received data * - If block based flow control is not supported by peer we * fall back to message based ditto, incrementing the counter */ static u16 tsk_inc(struct tipc_sock *tsk, int msglen) { if (likely(tsk->peer_caps & TIPC_BLOCK_FLOWCTL)) return ((msglen / FLOWCTL_BLK_SZ) + 1); return 1; |
301bae56f tipc: merge struc... |
201 |
} |
0c3141e91 [TIPC]: Overhaul ... |
202 |
/** |
2e84c60b7 tipc: remove incl... |
203 |
* tsk_advance_rx_queue - discard first buffer in socket receive queue |
0c3141e91 [TIPC]: Overhaul ... |
204 205 |
* * Caller must hold socket lock |
b97bf3fd8 [TIPC] Initial merge |
206 |
*/ |
2e84c60b7 tipc: remove incl... |
207 |
static void tsk_advance_rx_queue(struct sock *sk) |
b97bf3fd8 [TIPC] Initial merge |
208 |
{ |
5f6d9123f tipc: Eliminate t... |
209 |
kfree_skb(__skb_dequeue(&sk->sk_receive_queue)); |
b97bf3fd8 [TIPC] Initial merge |
210 |
} |
bcd3ffd4f tipc: introduce n... |
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
/* tipc_sk_respond() : send response message back to sender */ static void tipc_sk_respond(struct sock *sk, struct sk_buff *skb, int err) { u32 selector; u32 dnode; u32 onode = tipc_own_addr(sock_net(sk)); if (!tipc_msg_reverse(onode, &skb, err)) return; dnode = msg_destnode(buf_msg(skb)); selector = msg_origport(buf_msg(skb)); tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector); } |
0c3141e91 [TIPC]: Overhaul ... |
226 |
/** |
2e84c60b7 tipc: remove incl... |
227 |
* tsk_rej_rx_queue - reject all buffers in socket receive queue |
0c3141e91 [TIPC]: Overhaul ... |
228 229 |
* * Caller must hold socket lock |
b97bf3fd8 [TIPC] Initial merge |
230 |
*/ |
2e84c60b7 tipc: remove incl... |
231 |
static void tsk_rej_rx_queue(struct sock *sk) |
b97bf3fd8 [TIPC] Initial merge |
232 |
{ |
a6ca10944 tipc: use generic... |
233 |
struct sk_buff *skb; |
0c3141e91 [TIPC]: Overhaul ... |
234 |
|
bcd3ffd4f tipc: introduce n... |
235 236 |
while ((skb = __skb_dequeue(&sk->sk_receive_queue))) tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT); |
b97bf3fd8 [TIPC] Initial merge |
237 |
} |
d6fb7e9c9 tipc: remove tsk-... |
238 239 |
static bool tipc_sk_connected(struct sock *sk) { |
f40acbaf4 tipc: remove SS_C... |
240 |
return sk->sk_state == TIPC_ESTABLISHED; |
d6fb7e9c9 tipc: remove tsk-... |
241 |
} |
c752023aa tipc: remove sock... |
242 243 244 245 246 247 248 249 250 |
/* tipc_sk_type_connectionless - check if the socket is datagram socket * @sk: socket * * Returns true if connection less, false otherwise */ static bool tipc_sk_type_connectionless(struct sock *sk) { return sk->sk_type == SOCK_RDM || sk->sk_type == SOCK_DGRAM; } |
2e84c60b7 tipc: remove incl... |
251 |
/* tsk_peer_msg - verify if message was sent by connected port's peer |
0fc87aaeb tipc: remove sour... |
252 253 254 255 |
* * Handles cases where the node's network address has changed from * the default of <0.0.0> to its configured setting. */ |
2e84c60b7 tipc: remove incl... |
256 |
static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg) |
0fc87aaeb tipc: remove sour... |
257 |
{ |
d6fb7e9c9 tipc: remove tsk-... |
258 259 |
struct sock *sk = &tsk->sk; struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id); |
301bae56f tipc: merge struc... |
260 |
u32 peer_port = tsk_peer_port(tsk); |
0fc87aaeb tipc: remove sour... |
261 262 |
u32 orig_node; u32 peer_node; |
d6fb7e9c9 tipc: remove tsk-... |
263 |
if (unlikely(!tipc_sk_connected(sk))) |
0fc87aaeb tipc: remove sour... |
264 265 266 267 268 269 |
return false; if (unlikely(msg_origport(msg) != peer_port)) return false; orig_node = msg_orignode(msg); |
301bae56f tipc: merge struc... |
270 |
peer_node = tsk_peer_node(tsk); |
0fc87aaeb tipc: remove sour... |
271 272 273 |
if (likely(orig_node == peer_node)) return true; |
347475395 tipc: make tipc n... |
274 |
if (!orig_node && (peer_node == tn->own_addr)) |
0fc87aaeb tipc: remove sour... |
275 |
return true; |
347475395 tipc: make tipc n... |
276 |
if (!peer_node && (orig_node == tn->own_addr)) |
0fc87aaeb tipc: remove sour... |
277 278 279 280 |
return true; return false; } |
0c288c869 tipc: create TIPC... |
281 282 283 284 285 286 287 288 289 |
/* tipc_set_sk_state - set the sk_state of the socket * @sk: socket * * Caller must hold socket lock * * Returns 0 on success, errno otherwise */ static int tipc_set_sk_state(struct sock *sk, int state) { |
438adcaf0 tipc: create TIPC... |
290 |
int oldsk_state = sk->sk_state; |
0c288c869 tipc: create TIPC... |
291 292 293 |
int res = -EINVAL; switch (state) { |
438adcaf0 tipc: create TIPC... |
294 295 296 |
case TIPC_OPEN: res = 0; break; |
0c288c869 tipc: create TIPC... |
297 |
case TIPC_LISTEN: |
99a208898 tipc: create TIPC... |
298 |
case TIPC_CONNECTING: |
438adcaf0 tipc: create TIPC... |
299 |
if (oldsk_state == TIPC_OPEN) |
0c288c869 tipc: create TIPC... |
300 301 |
res = 0; break; |
8ea642ee9 tipc: create TIPC... |
302 |
case TIPC_ESTABLISHED: |
99a208898 tipc: create TIPC... |
303 |
if (oldsk_state == TIPC_CONNECTING || |
438adcaf0 tipc: create TIPC... |
304 |
oldsk_state == TIPC_OPEN) |
8ea642ee9 tipc: create TIPC... |
305 306 |
res = 0; break; |
9fd4b070f tipc: create TIPC... |
307 |
case TIPC_DISCONNECTING: |
99a208898 tipc: create TIPC... |
308 |
if (oldsk_state == TIPC_CONNECTING || |
9fd4b070f tipc: create TIPC... |
309 310 311 |
oldsk_state == TIPC_ESTABLISHED) res = 0; break; |
0c288c869 tipc: create TIPC... |
312 313 314 315 316 317 318 |
} if (!res) sk->sk_state = state; return res; } |
8c44e1af1 tipc: unify tipc_... |
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
static int tipc_sk_sock_err(struct socket *sock, long *timeout) { struct sock *sk = sock->sk; int err = sock_error(sk); int typ = sock->type; if (err) return err; if (typ == SOCK_STREAM || typ == SOCK_SEQPACKET) { if (sk->sk_state == TIPC_DISCONNECTING) return -EPIPE; else if (!tipc_sk_connected(sk)) return -ENOTCONN; } if (!*timeout) return -EAGAIN; if (signal_pending(current)) return sock_intr_errno(*timeout); return 0; } |
844cf763f tipc: make macro ... |
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
#define tipc_wait_for_cond(sock_, timeo_, condition_) \ ({ \ struct sock *sk_; \ int rc_; \ \ while ((rc_ = !(condition_))) { \ DEFINE_WAIT_FUNC(wait_, woken_wake_function); \ sk_ = (sock_)->sk; \ rc_ = tipc_sk_sock_err((sock_), timeo_); \ if (rc_) \ break; \ prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE); \ release_sock(sk_); \ *(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \ sched_annotate_sleep(); \ lock_sock(sk_); \ remove_wait_queue(sk_sleep(sk_), &wait_); \ } \ rc_; \ |
8c44e1af1 tipc: unify tipc_... |
359 |
}) |
b97bf3fd8 [TIPC] Initial merge |
360 |
/** |
c5fa7b3cf tipc: introduce n... |
361 |
* tipc_sk_create - create a TIPC socket |
0c3141e91 [TIPC]: Overhaul ... |
362 |
* @net: network namespace (must be default network) |
b97bf3fd8 [TIPC] Initial merge |
363 364 |
* @sock: pre-allocated socket structure * @protocol: protocol indicator (must be 0) |
3f378b684 net: pass kern to... |
365 |
* @kern: caused by kernel or by userspace? |
c43072852 [NET] TIPC: Fix w... |
366 |
* |
0c3141e91 [TIPC]: Overhaul ... |
367 368 |
* This routine creates additional data structures used by the TIPC socket, * initializes them, and links them together. |
b97bf3fd8 [TIPC] Initial merge |
369 370 371 |
* * Returns 0 on success, errno otherwise */ |
58ed94424 tipc: align usage... |
372 373 |
static int tipc_sk_create(struct net *net, struct socket *sock, int protocol, int kern) |
b97bf3fd8 [TIPC] Initial merge |
374 |
{ |
c5898636c tipc: reduce usag... |
375 |
struct tipc_net *tn; |
0c3141e91 [TIPC]: Overhaul ... |
376 |
const struct proto_ops *ops; |
b97bf3fd8 [TIPC] Initial merge |
377 |
struct sock *sk; |
58ed94424 tipc: align usage... |
378 |
struct tipc_sock *tsk; |
5b8fa7ce8 tipc: eliminate f... |
379 |
struct tipc_msg *msg; |
0c3141e91 [TIPC]: Overhaul ... |
380 381 |
/* Validate arguments */ |
b97bf3fd8 [TIPC] Initial merge |
382 383 |
if (unlikely(protocol != 0)) return -EPROTONOSUPPORT; |
b97bf3fd8 [TIPC] Initial merge |
384 385 |
switch (sock->type) { case SOCK_STREAM: |
0c3141e91 [TIPC]: Overhaul ... |
386 |
ops = &stream_ops; |
b97bf3fd8 [TIPC] Initial merge |
387 388 |
break; case SOCK_SEQPACKET: |
0c3141e91 [TIPC]: Overhaul ... |
389 |
ops = &packet_ops; |
b97bf3fd8 [TIPC] Initial merge |
390 391 |
break; case SOCK_DGRAM: |
b97bf3fd8 [TIPC] Initial merge |
392 |
case SOCK_RDM: |
0c3141e91 [TIPC]: Overhaul ... |
393 |
ops = &msg_ops; |
b97bf3fd8 [TIPC] Initial merge |
394 |
break; |
499786516 [TIPC]: Improved ... |
395 |
default: |
499786516 [TIPC]: Improved ... |
396 |
return -EPROTOTYPE; |
b97bf3fd8 [TIPC] Initial merge |
397 |
} |
0c3141e91 [TIPC]: Overhaul ... |
398 |
/* Allocate socket's protocol area */ |
11aa9c28b net: Pass kern fr... |
399 |
sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto, kern); |
0c3141e91 [TIPC]: Overhaul ... |
400 |
if (sk == NULL) |
b97bf3fd8 [TIPC] Initial merge |
401 |
return -ENOMEM; |
b97bf3fd8 [TIPC] Initial merge |
402 |
|
58ed94424 tipc: align usage... |
403 |
tsk = tipc_sk(sk); |
301bae56f tipc: merge struc... |
404 |
tsk->max_pkt = MAX_PKT_DEFAULT; |
301bae56f tipc: merge struc... |
405 |
INIT_LIST_HEAD(&tsk->publications); |
365ad353c tipc: reduce risk... |
406 |
INIT_LIST_HEAD(&tsk->cong_links); |
301bae56f tipc: merge struc... |
407 |
msg = &tsk->phdr; |
c5898636c tipc: reduce usag... |
408 |
tn = net_generic(sock_net(sk), tipc_net_id); |
b97bf3fd8 [TIPC] Initial merge |
409 |
|
0c3141e91 [TIPC]: Overhaul ... |
410 |
/* Finish initializing socket data structures */ |
0c3141e91 [TIPC]: Overhaul ... |
411 |
sock->ops = ops; |
0c3141e91 [TIPC]: Overhaul ... |
412 |
sock_init_data(sock, sk); |
438adcaf0 tipc: create TIPC... |
413 |
tipc_set_sk_state(sk, TIPC_OPEN); |
07f6c4bc0 tipc: convert tip... |
414 |
if (tipc_sk_insert(tsk)) { |
c19ca6cb4 treewide: Fix typ... |
415 416 |
pr_warn("Socket create failed; port number exhausted "); |
07f6c4bc0 tipc: convert tip... |
417 418 |
return -EINVAL; } |
40f9f4397 tipc: Fix tipc_sk... |
419 420 421 422 423 424 |
/* Ensure tsk is visible before we read own_addr. */ smp_mb(); tipc_msg_init(tn->own_addr, msg, TIPC_LOW_IMPORTANCE, TIPC_NAMED_MSG, NAMED_H_SIZE, 0); |
07f6c4bc0 tipc: convert tip... |
425 |
msg_set_origport(msg, tsk->portid); |
3721e9c7c tipc: remove redu... |
426 |
setup_timer(&sk->sk_timer, tipc_sk_timeout, (unsigned long)tsk); |
6f00089c7 tipc: remove SS_D... |
427 |
sk->sk_shutdown = 0; |
4f4482dcd tipc: compensate ... |
428 |
sk->sk_backlog_rcv = tipc_backlog_rcv; |
cc79dd1ba tipc: change sock... |
429 |
sk->sk_rcvbuf = sysctl_tipc_rmem[1]; |
f288bef46 tipc: fix race/in... |
430 431 |
sk->sk_data_ready = tipc_data_ready; sk->sk_write_space = tipc_write_space; |
f4195d1ea tipc: avoid packe... |
432 |
sk->sk_destruct = tipc_sock_destruct; |
4f4482dcd tipc: compensate ... |
433 434 |
tsk->conn_timeout = CONN_TIMEOUT_DEFAULT; atomic_set(&tsk->dupl_rcvcnt, 0); |
7ef43ebaa tipc: Fix race co... |
435 |
|
10724cc7b tipc: redesign co... |
436 437 438 |
/* Start out with safe limits until we receive an advertised window */ tsk->snd_win = tsk_adv_blocks(RCVBUF_MIN); tsk->rcv_win = tsk->snd_win; |
c752023aa tipc: remove sock... |
439 |
if (tipc_sk_type_connectionless(sk)) { |
301bae56f tipc: merge struc... |
440 |
tsk_set_unreturnable(tsk, true); |
0c3141e91 [TIPC]: Overhaul ... |
441 |
if (sock->type == SOCK_DGRAM) |
301bae56f tipc: merge struc... |
442 |
tsk_set_unreliable(tsk, true); |
0c3141e91 [TIPC]: Overhaul ... |
443 |
} |
438adcaf0 tipc: create TIPC... |
444 |
|
b97bf3fd8 [TIPC] Initial merge |
445 446 |
return 0; } |
07f6c4bc0 tipc: convert tip... |
447 448 449 450 451 452 |
static void tipc_sk_callback(struct rcu_head *head) { struct tipc_sock *tsk = container_of(head, struct tipc_sock, rcu); sock_put(&tsk->sk); } |
6f00089c7 tipc: remove SS_D... |
453 454 455 456 457 458 |
/* Caller should hold socket lock for the socket. */ static void __tipc_shutdown(struct socket *sock, int error) { struct sock *sk = sock->sk; struct tipc_sock *tsk = tipc_sk(sk); struct net *net = sock_net(sk); |
365ad353c tipc: reduce risk... |
459 |
long timeout = CONN_TIMEOUT_DEFAULT; |
6f00089c7 tipc: remove SS_D... |
460 461 |
u32 dnode = tsk_peer_node(tsk); struct sk_buff *skb; |
365ad353c tipc: reduce risk... |
462 463 464 |
/* Avoid that hi-prio shutdown msgs bypass msgs in link wakeup queue */ tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt && !tsk_conn_cong(tsk))); |
6f00089c7 tipc: remove SS_D... |
465 466 467 468 469 470 |
/* Reject all unreceived messages, except on an active connection * (which disconnects locally & sends a 'FIN+' to peer). */ while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) { if (TIPC_SKB_CB(skb)->bytes_read) { kfree_skb(skb); |
693c56491 tipc: don't send ... |
471 |
continue; |
6f00089c7 tipc: remove SS_D... |
472 |
} |
693c56491 tipc: don't send ... |
473 474 475 476 477 478 |
if (!tipc_sk_type_connectionless(sk) && sk->sk_state != TIPC_DISCONNECTING) { tipc_set_sk_state(sk, TIPC_DISCONNECTING); tipc_node_remove_conn(net, dnode, tsk->portid); } tipc_sk_respond(sk, skb, error); |
6f00089c7 tipc: remove SS_D... |
479 |
} |
693c56491 tipc: don't send ... |
480 481 482 |
if (tipc_sk_type_connectionless(sk)) return; |
6f00089c7 tipc: remove SS_D... |
483 484 485 486 487 488 489 |
if (sk->sk_state != TIPC_DISCONNECTING) { skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode, tsk_own_node(tsk), tsk_peer_port(tsk), tsk->portid, error); if (skb) tipc_node_xmit_skb(net, skb, dnode, tsk->portid); |
693c56491 tipc: don't send ... |
490 491 |
tipc_node_remove_conn(net, dnode, tsk->portid); tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
6f00089c7 tipc: remove SS_D... |
492 493 |
} } |
c5fa7b3cf tipc: introduce n... |
494 |
/** |
247f0f3c3 tipc: align tipc ... |
495 |
* tipc_release - destroy a TIPC socket |
b97bf3fd8 [TIPC] Initial merge |
496 497 498 499 500 501 502 |
* @sock: socket to destroy * * This routine cleans up any messages that are still queued on the socket. * For DGRAM and RDM socket types, all queued messages are rejected. * For SEQPACKET and STREAM socket types, the first message is rejected * and any others are discarded. (If the first message on a STREAM socket * is partially-read, it is discarded and the next one is rejected instead.) |
c43072852 [NET] TIPC: Fix w... |
503 |
* |
b97bf3fd8 [TIPC] Initial merge |
504 505 506 507 508 509 |
* NOTE: Rejected messages are not necessarily returned to the sender! They * are returned or discarded according to the "destination droppable" setting * specified for the message by the sender. * * Returns 0 on success, errno otherwise */ |
247f0f3c3 tipc: align tipc ... |
510 |
static int tipc_release(struct socket *sock) |
b97bf3fd8 [TIPC] Initial merge |
511 |
{ |
b97bf3fd8 [TIPC] Initial merge |
512 |
struct sock *sk = sock->sk; |
58ed94424 tipc: align usage... |
513 |
struct tipc_sock *tsk; |
b97bf3fd8 [TIPC] Initial merge |
514 |
|
0c3141e91 [TIPC]: Overhaul ... |
515 516 517 518 |
/* * Exit if socket isn't fully initialized (occurs when a failed accept() * releases a pre-allocated child socket that was never used) */ |
0c3141e91 [TIPC]: Overhaul ... |
519 |
if (sk == NULL) |
b97bf3fd8 [TIPC] Initial merge |
520 |
return 0; |
c43072852 [NET] TIPC: Fix w... |
521 |
|
58ed94424 tipc: align usage... |
522 |
tsk = tipc_sk(sk); |
0c3141e91 [TIPC]: Overhaul ... |
523 |
lock_sock(sk); |
6f00089c7 tipc: remove SS_D... |
524 525 |
__tipc_shutdown(sock, TIPC_ERR_NO_PORT); sk->sk_shutdown = SHUTDOWN_MASK; |
301bae56f tipc: merge struc... |
526 |
tipc_sk_withdraw(tsk, 0, NULL); |
1ea23a211 tipc: uncondition... |
527 |
sk_stop_timer(sk, &sk->sk_timer); |
07f6c4bc0 tipc: convert tip... |
528 |
tipc_sk_remove(tsk); |
b97bf3fd8 [TIPC] Initial merge |
529 |
|
0c3141e91 [TIPC]: Overhaul ... |
530 |
/* Reject any messages that accumulated in backlog queue */ |
0c3141e91 [TIPC]: Overhaul ... |
531 |
release_sock(sk); |
365ad353c tipc: reduce risk... |
532 533 |
u32_list_purge(&tsk->cong_links); tsk->cong_link_cnt = 0; |
07f6c4bc0 tipc: convert tip... |
534 |
call_rcu(&tsk->rcu, tipc_sk_callback); |
0c3141e91 [TIPC]: Overhaul ... |
535 |
sock->sk = NULL; |
b97bf3fd8 [TIPC] Initial merge |
536 |
|
065d7e395 tipc: Let tipc_re... |
537 |
return 0; |
b97bf3fd8 [TIPC] Initial merge |
538 539 540 |
} /** |
247f0f3c3 tipc: align tipc ... |
541 |
* tipc_bind - associate or disassocate TIPC name(s) with a socket |
b97bf3fd8 [TIPC] Initial merge |
542 543 544 |
* @sock: socket structure * @uaddr: socket address describing name(s) and desired operation * @uaddr_len: size of socket address data structure |
c43072852 [NET] TIPC: Fix w... |
545 |
* |
b97bf3fd8 [TIPC] Initial merge |
546 547 548 |
* Name and name sequence binding is indicated using a positive scope value; * a negative scope value unbinds the specified name. Specifying no name * (i.e. a socket address length of 0) unbinds all names from the socket. |
c43072852 [NET] TIPC: Fix w... |
549 |
* |
b97bf3fd8 [TIPC] Initial merge |
550 |
* Returns 0 on success, errno otherwise |
0c3141e91 [TIPC]: Overhaul ... |
551 552 553 |
* * NOTE: This routine doesn't need to take the socket lock since it doesn't * access any non-constant socket information. |
b97bf3fd8 [TIPC] Initial merge |
554 |
*/ |
247f0f3c3 tipc: align tipc ... |
555 556 |
static int tipc_bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) |
b97bf3fd8 [TIPC] Initial merge |
557 |
{ |
84602761c tipc: fix deadloc... |
558 |
struct sock *sk = sock->sk; |
b97bf3fd8 [TIPC] Initial merge |
559 |
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
58ed94424 tipc: align usage... |
560 |
struct tipc_sock *tsk = tipc_sk(sk); |
84602761c tipc: fix deadloc... |
561 |
int res = -EINVAL; |
b97bf3fd8 [TIPC] Initial merge |
562 |
|
84602761c tipc: fix deadloc... |
563 564 |
lock_sock(sk); if (unlikely(!uaddr_len)) { |
301bae56f tipc: merge struc... |
565 |
res = tipc_sk_withdraw(tsk, 0, NULL); |
84602761c tipc: fix deadloc... |
566 567 |
goto exit; } |
c43072852 [NET] TIPC: Fix w... |
568 |
|
84602761c tipc: fix deadloc... |
569 570 571 572 573 574 575 576 |
if (uaddr_len < sizeof(struct sockaddr_tipc)) { res = -EINVAL; goto exit; } if (addr->family != AF_TIPC) { res = -EAFNOSUPPORT; goto exit; } |
b97bf3fd8 [TIPC] Initial merge |
577 |
|
b97bf3fd8 [TIPC] Initial merge |
578 579 |
if (addr->addrtype == TIPC_ADDR_NAME) addr->addr.nameseq.upper = addr->addr.nameseq.lower; |
84602761c tipc: fix deadloc... |
580 581 582 583 |
else if (addr->addrtype != TIPC_ADDR_NAMESEQ) { res = -EAFNOSUPPORT; goto exit; } |
c43072852 [NET] TIPC: Fix w... |
584 |
|
13a2e8987 tipc: convert top... |
585 |
if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && |
7d0ab17b7 tipc: convert con... |
586 |
(addr->addr.nameseq.type != TIPC_TOP_SRV) && |
84602761c tipc: fix deadloc... |
587 588 589 590 |
(addr->addr.nameseq.type != TIPC_CFG_SRV)) { res = -EACCES; goto exit; } |
c422f1bdc tipc: Simplify en... |
591 |
|
84602761c tipc: fix deadloc... |
592 |
res = (addr->scope > 0) ? |
301bae56f tipc: merge struc... |
593 594 |
tipc_sk_publish(tsk, addr->scope, &addr->addr.nameseq) : tipc_sk_withdraw(tsk, -addr->scope, &addr->addr.nameseq); |
84602761c tipc: fix deadloc... |
595 596 597 |
exit: release_sock(sk); return res; |
b97bf3fd8 [TIPC] Initial merge |
598 |
} |
c43072852 [NET] TIPC: Fix w... |
599 |
/** |
247f0f3c3 tipc: align tipc ... |
600 |
* tipc_getname - get port ID of socket or peer socket |
b97bf3fd8 [TIPC] Initial merge |
601 602 603 |
* @sock: socket structure * @uaddr: area for returned socket address * @uaddr_len: area for returned length of socket address |
2da59918e tipc: Fix race co... |
604 |
* @peer: 0 = own ID, 1 = current peer ID, 2 = current/former peer ID |
c43072852 [NET] TIPC: Fix w... |
605 |
* |
b97bf3fd8 [TIPC] Initial merge |
606 |
* Returns 0 on success, errno otherwise |
0c3141e91 [TIPC]: Overhaul ... |
607 |
* |
2da59918e tipc: Fix race co... |
608 609 |
* NOTE: This routine doesn't need to take the socket lock since it only * accesses socket information that is unchanging (or which changes in |
0e65967e3 tipc: cleanup var... |
610 |
* a completely predictable manner). |
b97bf3fd8 [TIPC] Initial merge |
611 |
*/ |
247f0f3c3 tipc: align tipc ... |
612 613 |
static int tipc_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) |
b97bf3fd8 [TIPC] Initial merge |
614 |
{ |
b97bf3fd8 [TIPC] Initial merge |
615 |
struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
9fd4b070f tipc: create TIPC... |
616 617 |
struct sock *sk = sock->sk; struct tipc_sock *tsk = tipc_sk(sk); |
347475395 tipc: make tipc n... |
618 |
struct tipc_net *tn = net_generic(sock_net(sock->sk), tipc_net_id); |
b97bf3fd8 [TIPC] Initial merge |
619 |
|
88f8a5e3e net: tipc: fix in... |
620 |
memset(addr, 0, sizeof(*addr)); |
0c3141e91 [TIPC]: Overhaul ... |
621 |
if (peer) { |
f40acbaf4 tipc: remove SS_C... |
622 |
if ((!tipc_sk_connected(sk)) && |
9fd4b070f tipc: create TIPC... |
623 |
((peer != 2) || (sk->sk_state != TIPC_DISCONNECTING))) |
2da59918e tipc: Fix race co... |
624 |
return -ENOTCONN; |
301bae56f tipc: merge struc... |
625 626 |
addr->addr.id.ref = tsk_peer_port(tsk); addr->addr.id.node = tsk_peer_node(tsk); |
0c3141e91 [TIPC]: Overhaul ... |
627 |
} else { |
07f6c4bc0 tipc: convert tip... |
628 |
addr->addr.id.ref = tsk->portid; |
347475395 tipc: make tipc n... |
629 |
addr->addr.id.node = tn->own_addr; |
0c3141e91 [TIPC]: Overhaul ... |
630 |
} |
b97bf3fd8 [TIPC] Initial merge |
631 632 633 634 635 |
*uaddr_len = sizeof(*addr); addr->addrtype = TIPC_ADDR_ID; addr->family = AF_TIPC; addr->scope = 0; |
b97bf3fd8 [TIPC] Initial merge |
636 |
addr->addr.name.domain = 0; |
0c3141e91 [TIPC]: Overhaul ... |
637 |
return 0; |
b97bf3fd8 [TIPC] Initial merge |
638 639 640 |
} /** |
247f0f3c3 tipc: align tipc ... |
641 |
* tipc_poll - read and possibly block on pollmask |
b97bf3fd8 [TIPC] Initial merge |
642 643 644 645 |
* @file: file structure associated with the socket * @sock: socket for which to calculate the poll bits * @wait: ??? * |
9b674e82b [TIPC]: Cosmetic ... |
646 647 648 649 650 651 652 653 |
* Returns pollmask value * * COMMENTARY: * It appears that the usual socket locking mechanisms are not useful here * since the pollmask info is potentially out-of-date the moment this routine * exits. TCP and other protocols seem to rely on higher level poll routines * to handle any preventable race conditions, so TIPC will do the same ... * |
f662c0705 tipc: correct pro... |
654 655 656 |
* IMPORTANT: The fact that a read or write operation is indicated does NOT * imply that the operation will succeed, merely that it should be performed * and will not block. |
b97bf3fd8 [TIPC] Initial merge |
657 |
*/ |
247f0f3c3 tipc: align tipc ... |
658 659 |
static unsigned int tipc_poll(struct file *file, struct socket *sock, poll_table *wait) |
b97bf3fd8 [TIPC] Initial merge |
660 |
{ |
9b674e82b [TIPC]: Cosmetic ... |
661 |
struct sock *sk = sock->sk; |
58ed94424 tipc: align usage... |
662 |
struct tipc_sock *tsk = tipc_sk(sk); |
f662c0705 tipc: correct pro... |
663 |
u32 mask = 0; |
9b674e82b [TIPC]: Cosmetic ... |
664 |
|
f288bef46 tipc: fix race/in... |
665 |
sock_poll_wait(file, sk_sleep(sk), wait); |
9b674e82b [TIPC]: Cosmetic ... |
666 |
|
6f00089c7 tipc: remove SS_D... |
667 668 669 670 |
if (sk->sk_shutdown & RCV_SHUTDOWN) mask |= POLLRDHUP | POLLIN | POLLRDNORM; if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= POLLHUP; |
f40acbaf4 tipc: remove SS_C... |
671 672 |
switch (sk->sk_state) { case TIPC_ESTABLISHED: |
92ae82334 tipc: fix hanging... |
673 |
case TIPC_CONNECTING: |
365ad353c tipc: reduce risk... |
674 |
if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk)) |
f662c0705 tipc: correct pro... |
675 |
mask |= POLLOUT; |
f40acbaf4 tipc: remove SS_C... |
676 677 |
/* fall thru' */ case TIPC_LISTEN: |
f662c0705 tipc: correct pro... |
678 679 |
if (!skb_queue_empty(&sk->sk_receive_queue)) mask |= (POLLIN | POLLRDNORM); |
f40acbaf4 tipc: remove SS_C... |
680 681 |
break; case TIPC_OPEN: |
365ad353c tipc: reduce risk... |
682 |
if (!tsk->cong_link_cnt) |
f40acbaf4 tipc: remove SS_C... |
683 684 685 686 687 688 689 690 |
mask |= POLLOUT; if (tipc_sk_type_connectionless(sk) && (!skb_queue_empty(&sk->sk_receive_queue))) mask |= (POLLIN | POLLRDNORM); break; case TIPC_DISCONNECTING: mask = (POLLIN | POLLRDNORM | POLLHUP); break; |
f662c0705 tipc: correct pro... |
691 |
} |
9b674e82b [TIPC]: Cosmetic ... |
692 693 |
return mask; |
b97bf3fd8 [TIPC] Initial merge |
694 |
} |
0abd8ff21 tipc: start using... |
695 696 697 698 |
/** * tipc_sendmcast - send multicast message * @sock: socket structure * @seq: destination address |
562640f3c tipc_sendmsg(): p... |
699 |
* @msg: message to send |
365ad353c tipc: reduce risk... |
700 701 |
* @dlen: length of data to send * @timeout: timeout to wait for wakeup |
0abd8ff21 tipc: start using... |
702 703 704 705 706 |
* * Called from function tipc_sendmsg(), which has done all sanity checks * Returns the number of bytes sent on success, or errno */ static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, |
365ad353c tipc: reduce risk... |
707 |
struct msghdr *msg, size_t dlen, long timeout) |
0abd8ff21 tipc: start using... |
708 709 |
{ struct sock *sk = sock->sk; |
c5898636c tipc: reduce usag... |
710 |
struct tipc_sock *tsk = tipc_sk(sk); |
365ad353c tipc: reduce risk... |
711 |
struct tipc_msg *hdr = &tsk->phdr; |
f2f9800d4 tipc: make tipc n... |
712 |
struct net *net = sock_net(sk); |
365ad353c tipc: reduce risk... |
713 |
int mtu = tipc_bcast_get_mtu(net); |
01fd12bb1 tipc: make replic... |
714 |
struct tipc_mc_method *method = &tsk->mc_method; |
a853e4c6d tipc: introduce r... |
715 |
u32 domain = addr_domain(net, TIPC_CLUSTER_SCOPE); |
365ad353c tipc: reduce risk... |
716 |
struct sk_buff_head pkts; |
a853e4c6d tipc: introduce r... |
717 |
struct tipc_nlist dsts; |
0abd8ff21 tipc: start using... |
718 |
int rc; |
a853e4c6d tipc: introduce r... |
719 |
/* Block or return if any destination link is congested */ |
365ad353c tipc: reduce risk... |
720 721 722 |
rc = tipc_wait_for_cond(sock, &timeout, !tsk->cong_link_cnt); if (unlikely(rc)) return rc; |
f214fc402 tipc: Revert "tip... |
723 |
|
a853e4c6d tipc: introduce r... |
724 725 726 727 728 729 730 731 |
/* Lookup destination nodes */ tipc_nlist_init(&dsts, tipc_own_addr(net)); tipc_nametbl_lookup_dst_nodes(net, seq->type, seq->lower, seq->upper, domain, &dsts); if (!dsts.local && !dsts.remote) return -EHOSTUNREACH; /* Build message header */ |
365ad353c tipc: reduce risk... |
732 |
msg_set_type(hdr, TIPC_MCAST_MSG); |
a853e4c6d tipc: introduce r... |
733 |
msg_set_hdr_sz(hdr, MCAST_H_SIZE); |
365ad353c tipc: reduce risk... |
734 735 736 737 738 739 |
msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE); msg_set_destport(hdr, 0); msg_set_destnode(hdr, 0); msg_set_nametype(hdr, seq->type); msg_set_namelower(hdr, seq->lower); msg_set_nameupper(hdr, seq->upper); |
365ad353c tipc: reduce risk... |
740 |
|
a853e4c6d tipc: introduce r... |
741 |
/* Build message as chain of buffers */ |
365ad353c tipc: reduce risk... |
742 743 |
skb_queue_head_init(&pkts); rc = tipc_msg_build(hdr, msg, 0, dlen, mtu, &pkts); |
0abd8ff21 tipc: start using... |
744 |
|
a853e4c6d tipc: introduce r... |
745 746 |
/* Send message if build was successful */ if (unlikely(rc == dlen)) |
01fd12bb1 tipc: make replic... |
747 |
rc = tipc_mcast_xmit(net, &pkts, method, &dsts, |
a853e4c6d tipc: introduce r... |
748 749 750 |
&tsk->cong_link_cnt); tipc_nlist_purge(&dsts); |
365ad353c tipc: reduce risk... |
751 752 |
return rc ? rc : dlen; |
0abd8ff21 tipc: start using... |
753 |
} |
cb1b72809 tipc: eliminate r... |
754 755 756 757 758 759 |
/** * tipc_sk_mcast_rcv - Deliver multicast messages to all destination sockets * @arrvq: queue with arriving messages, to be cloned after destination lookup * @inputq: queue with cloned messages, delivered to socket after dest lookup * * Multi-threaded: parallel calls with reference to same queues may occur |
078bec826 tipc: add new fun... |
760 |
*/ |
cb1b72809 tipc: eliminate r... |
761 762 |
void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, struct sk_buff_head *inputq) |
078bec826 tipc: add new fun... |
763 |
{ |
cb1b72809 tipc: eliminate r... |
764 |
struct tipc_msg *msg; |
4d8642d89 tipc: modify stru... |
765 |
struct list_head dports; |
3c724acdd tipc: simplify so... |
766 |
u32 portid; |
078bec826 tipc: add new fun... |
767 |
u32 scope = TIPC_CLUSTER_SCOPE; |
cb1b72809 tipc: eliminate r... |
768 769 770 |
struct sk_buff_head tmpq; uint hsz; struct sk_buff *skb, *_skb; |
3c724acdd tipc: simplify so... |
771 |
|
cb1b72809 tipc: eliminate r... |
772 |
__skb_queue_head_init(&tmpq); |
4d8642d89 tipc: modify stru... |
773 |
INIT_LIST_HEAD(&dports); |
078bec826 tipc: add new fun... |
774 |
|
cb1b72809 tipc: eliminate r... |
775 776 777 778 779 780 781 782 783 784 785 786 |
skb = tipc_skb_peek(arrvq, &inputq->lock); for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { msg = buf_msg(skb); hsz = skb_headroom(skb) + msg_hdr_sz(msg); if (in_own_node(net, msg_orignode(msg))) scope = TIPC_NODE_SCOPE; /* Create destination port list and message clones: */ tipc_nametbl_mc_translate(net, msg_nametype(msg), msg_namelower(msg), msg_nameupper(msg), scope, &dports); |
4d8642d89 tipc: modify stru... |
787 788 |
portid = u32_pop(&dports); for (; portid; portid = u32_pop(&dports)) { |
cb1b72809 tipc: eliminate r... |
789 790 791 792 793 794 795 796 |
_skb = __pskb_copy(skb, hsz, GFP_ATOMIC); if (_skb) { msg_set_destport(buf_msg(_skb), portid); __skb_queue_tail(&tmpq, _skb); continue; } pr_warn("Failed to clone mcast rcv buffer "); |
078bec826 tipc: add new fun... |
797 |
} |
cb1b72809 tipc: eliminate r... |
798 799 800 801 802 803 804 805 806 |
/* Append to inputq if not already done by other thread */ spin_lock_bh(&inputq->lock); if (skb_peek(arrvq) == skb) { skb_queue_splice_tail_init(&tmpq, inputq); kfree_skb(__skb_dequeue(arrvq)); } spin_unlock_bh(&inputq->lock); __skb_queue_purge(&tmpq); kfree_skb(skb); |
078bec826 tipc: add new fun... |
807 |
} |
cb1b72809 tipc: eliminate r... |
808 |
tipc_sk_rcv(net, inputq); |
078bec826 tipc: add new fun... |
809 |
} |
c43072852 [NET] TIPC: Fix w... |
810 |
/** |
ac0074ee7 tipc: clean up co... |
811 812 |
* tipc_sk_proto_rcv - receive a connection mng protocol message * @tsk: receiving socket |
bcd3ffd4f tipc: introduce n... |
813 |
* @skb: pointer to message buffer. |
ac0074ee7 tipc: clean up co... |
814 |
*/ |
f1d048f24 tipc: fix socket ... |
815 816 |
static void tipc_sk_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb, struct sk_buff_head *xmitq) |
ac0074ee7 tipc: clean up co... |
817 |
{ |
bcd3ffd4f tipc: introduce n... |
818 |
struct sock *sk = &tsk->sk; |
f1d048f24 tipc: fix socket ... |
819 |
u32 onode = tsk_own_node(tsk); |
bcd3ffd4f tipc: introduce n... |
820 821 |
struct tipc_msg *hdr = buf_msg(skb); int mtyp = msg_type(hdr); |
10724cc7b tipc: redesign co... |
822 |
bool conn_cong; |
bcd3ffd4f tipc: introduce n... |
823 |
|
ac0074ee7 tipc: clean up co... |
824 |
/* Ignore if connection cannot be validated: */ |
bcd3ffd4f tipc: introduce n... |
825 |
if (!tsk_peer_msg(tsk, hdr)) |
ac0074ee7 tipc: clean up co... |
826 |
goto exit; |
c1be77562 tipc: close the c... |
827 828 829 830 831 832 833 |
if (unlikely(msg_errcode(hdr))) { tipc_set_sk_state(sk, TIPC_DISCONNECTING); tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk), tsk_peer_port(tsk)); sk->sk_state_change(sk); goto exit; } |
8ea642ee9 tipc: create TIPC... |
834 |
tsk->probe_unacked = false; |
ac0074ee7 tipc: clean up co... |
835 |
|
bcd3ffd4f tipc: introduce n... |
836 837 |
if (mtyp == CONN_PROBE) { msg_set_type(hdr, CONN_PROBE_REPLY); |
f1d048f24 tipc: fix socket ... |
838 839 |
if (tipc_msg_reverse(onode, &skb, TIPC_OK)) __skb_queue_tail(xmitq, skb); |
bcd3ffd4f tipc: introduce n... |
840 841 |
return; } else if (mtyp == CONN_ACK) { |
301bae56f tipc: merge struc... |
842 |
conn_cong = tsk_conn_cong(tsk); |
10724cc7b tipc: redesign co... |
843 844 845 |
tsk->snt_unacked -= msg_conn_ack(hdr); if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL) tsk->snd_win = msg_adv_win(hdr); |
60120526c tipc: simplify co... |
846 |
if (conn_cong) |
bcd3ffd4f tipc: introduce n... |
847 848 849 850 |
sk->sk_write_space(sk); } else if (mtyp != CONN_PROBE_REPLY) { pr_warn("Received unknown CONN_PROTO msg "); |
ac0074ee7 tipc: clean up co... |
851 |
} |
ac0074ee7 tipc: clean up co... |
852 |
exit: |
bcd3ffd4f tipc: introduce n... |
853 |
kfree_skb(skb); |
ac0074ee7 tipc: clean up co... |
854 |
} |
e2dafe87d tipc: RDM/DGRAM t... |
855 |
/** |
247f0f3c3 tipc: align tipc ... |
856 |
* tipc_sendmsg - send message in connectionless manner |
b97bf3fd8 [TIPC] Initial merge |
857 858 |
* @sock: socket structure * @m: message to send |
e2dafe87d tipc: RDM/DGRAM t... |
859 |
* @dsz: amount of user data to be sent |
c43072852 [NET] TIPC: Fix w... |
860 |
* |
b97bf3fd8 [TIPC] Initial merge |
861 |
* Message must have an destination specified explicitly. |
c43072852 [NET] TIPC: Fix w... |
862 |
* Used for SOCK_RDM and SOCK_DGRAM messages, |
b97bf3fd8 [TIPC] Initial merge |
863 864 |
* and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections. * (Note: 'SYN+' is prohibited on SOCK_STREAM.) |
c43072852 [NET] TIPC: Fix w... |
865 |
* |
b97bf3fd8 [TIPC] Initial merge |
866 867 |
* Returns the number of bytes sent on success, or errno otherwise */ |
1b7841404 net: Remove iocb ... |
868 |
static int tipc_sendmsg(struct socket *sock, |
e2dafe87d tipc: RDM/DGRAM t... |
869 |
struct msghdr *m, size_t dsz) |
b97bf3fd8 [TIPC] Initial merge |
870 |
{ |
39a0295f9 tipc: Don't use i... |
871 872 873 874 875 876 877 878 879 |
struct sock *sk = sock->sk; int ret; lock_sock(sk); ret = __tipc_sendmsg(sock, m, dsz); release_sock(sk); return ret; } |
365ad353c tipc: reduce risk... |
880 |
static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen) |
39a0295f9 tipc: Don't use i... |
881 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
882 |
struct sock *sk = sock->sk; |
f2f9800d4 tipc: make tipc n... |
883 |
struct net *net = sock_net(sk); |
365ad353c tipc: reduce risk... |
884 885 886 887 888 889 |
struct tipc_sock *tsk = tipc_sk(sk); DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); struct list_head *clinks = &tsk->cong_links; bool syn = !tipc_sk_type_connectionless(sk); struct tipc_msg *hdr = &tsk->phdr; |
f2f8036e3 tipc: add support... |
890 |
struct tipc_name_seq *seq; |
365ad353c tipc: reduce risk... |
891 892 893 894 |
struct sk_buff_head pkts; u32 type, inst, domain; u32 dnode, dport; int mtu, rc; |
b97bf3fd8 [TIPC] Initial merge |
895 |
|
365ad353c tipc: reduce risk... |
896 |
if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE)) |
c29c3f70c tipc: Abort exces... |
897 |
return -EMSGSIZE; |
365ad353c tipc: reduce risk... |
898 |
|
f2f8036e3 tipc: add support... |
899 |
if (unlikely(!dest)) { |
365ad353c tipc: reduce risk... |
900 901 |
dest = &tsk->peer; if (!syn || dest->family != AF_TIPC) |
f2f8036e3 tipc: add support... |
902 |
return -EDESTADDRREQ; |
f2f8036e3 tipc: add support... |
903 |
} |
365ad353c tipc: reduce risk... |
904 905 906 907 908 909 910 911 |
if (unlikely(m->msg_namelen < sizeof(*dest))) return -EINVAL; if (unlikely(dest->family != AF_TIPC)) return -EINVAL; if (unlikely(syn)) { |
0c288c869 tipc: create TIPC... |
912 |
if (sk->sk_state == TIPC_LISTEN) |
39a0295f9 tipc: Don't use i... |
913 |
return -EPIPE; |
438adcaf0 tipc: create TIPC... |
914 |
if (sk->sk_state != TIPC_OPEN) |
39a0295f9 tipc: Don't use i... |
915 916 917 |
return -EISCONN; if (tsk->published) return -EOPNOTSUPP; |
3388007bc [TIPC]: Implied c... |
918 |
if (dest->addrtype == TIPC_ADDR_NAME) { |
301bae56f tipc: merge struc... |
919 920 |
tsk->conn_type = dest->addr.name.name.type; tsk->conn_instance = dest->addr.name.name.instance; |
3388007bc [TIPC]: Implied c... |
921 |
} |
b97bf3fd8 [TIPC] Initial merge |
922 |
} |
e2dafe87d tipc: RDM/DGRAM t... |
923 |
|
365ad353c tipc: reduce risk... |
924 925 926 |
seq = &dest->addr.nameseq; if (dest->addrtype == TIPC_ADDR_MCAST) return tipc_sendmcast(sock, seq, m, dlen, timeout); |
e2dafe87d tipc: RDM/DGRAM t... |
927 |
|
365ad353c tipc: reduce risk... |
928 929 930 931 |
if (dest->addrtype == TIPC_ADDR_NAME) { type = dest->addr.name.name.type; inst = dest->addr.name.name.instance; domain = dest->addr.name.domain; |
e2dafe87d tipc: RDM/DGRAM t... |
932 |
dnode = domain; |
365ad353c tipc: reduce risk... |
933 934 935 936 937 |
msg_set_type(hdr, TIPC_NAMED_MSG); msg_set_hdr_sz(hdr, NAMED_H_SIZE); msg_set_nametype(hdr, type); msg_set_nameinst(hdr, inst); msg_set_lookup_scope(hdr, tipc_addr_scope(domain)); |
4ac1c8d0e tipc: name tipc n... |
938 |
dport = tipc_nametbl_translate(net, type, inst, &dnode); |
365ad353c tipc: reduce risk... |
939 940 |
msg_set_destnode(hdr, dnode); msg_set_destport(hdr, dport); |
39a0295f9 tipc: Don't use i... |
941 942 |
if (unlikely(!dport && !dnode)) return -EHOSTUNREACH; |
365ad353c tipc: reduce risk... |
943 |
|
e2dafe87d tipc: RDM/DGRAM t... |
944 945 |
} else if (dest->addrtype == TIPC_ADDR_ID) { dnode = dest->addr.id.node; |
365ad353c tipc: reduce risk... |
946 947 948 949 950 |
msg_set_type(hdr, TIPC_DIRECT_MSG); msg_set_lookup_scope(hdr, 0); msg_set_destnode(hdr, dnode); msg_set_destport(hdr, dest->addr.id.ref); msg_set_hdr_sz(hdr, BASIC_H_SIZE); |
e2dafe87d tipc: RDM/DGRAM t... |
951 |
} |
365ad353c tipc: reduce risk... |
952 953 954 955 956 957 |
/* Block or return if destination link is congested */ rc = tipc_wait_for_cond(sock, &timeout, !u32_find(clinks, dnode)); if (unlikely(rc)) return rc; skb_queue_head_init(&pkts); |
f2f9800d4 tipc: make tipc n... |
958 |
mtu = tipc_node_get_mtu(net, dnode, tsk->portid); |
365ad353c tipc: reduce risk... |
959 960 |
rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts); if (unlikely(rc != dlen)) |
39a0295f9 tipc: Don't use i... |
961 |
return rc; |
e2dafe87d tipc: RDM/DGRAM t... |
962 |
|
365ad353c tipc: reduce risk... |
963 964 965 966 967 968 |
rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid); if (unlikely(rc == -ELINKCONG)) { u32_push(clinks, dnode); tsk->cong_link_cnt++; rc = 0; } |
e2dafe87d tipc: RDM/DGRAM t... |
969 |
|
365ad353c tipc: reduce risk... |
970 971 972 973 |
if (unlikely(syn && !rc)) tipc_set_sk_state(sk, TIPC_CONNECTING); return rc ? rc : dlen; |
b97bf3fd8 [TIPC] Initial merge |
974 |
} |
c43072852 [NET] TIPC: Fix w... |
975 |
/** |
365ad353c tipc: reduce risk... |
976 |
* tipc_sendstream - send stream-oriented data |
b97bf3fd8 [TIPC] Initial merge |
977 |
* @sock: socket structure |
4ccfe5e04 tipc: connection ... |
978 979 |
* @m: data to send * @dsz: total length of data to be transmitted |
c43072852 [NET] TIPC: Fix w... |
980 |
* |
4ccfe5e04 tipc: connection ... |
981 |
* Used for SOCK_STREAM data. |
c43072852 [NET] TIPC: Fix w... |
982 |
* |
4ccfe5e04 tipc: connection ... |
983 984 |
* Returns the number of bytes sent on success (or partial success), * or errno if no data sent |
b97bf3fd8 [TIPC] Initial merge |
985 |
*/ |
365ad353c tipc: reduce risk... |
986 |
static int tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dsz) |
b97bf3fd8 [TIPC] Initial merge |
987 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
988 |
struct sock *sk = sock->sk; |
39a0295f9 tipc: Don't use i... |
989 990 991 |
int ret; lock_sock(sk); |
365ad353c tipc: reduce risk... |
992 |
ret = __tipc_sendstream(sock, m, dsz); |
39a0295f9 tipc: Don't use i... |
993 994 995 996 |
release_sock(sk); return ret; } |
365ad353c tipc: reduce risk... |
997 |
static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dlen) |
39a0295f9 tipc: Don't use i... |
998 999 |
{ struct sock *sk = sock->sk; |
342dfc306 net: add build-ti... |
1000 |
DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
365ad353c tipc: reduce risk... |
1001 1002 1003 1004 1005 1006 1007 1008 |
long timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); struct tipc_sock *tsk = tipc_sk(sk); struct tipc_msg *hdr = &tsk->phdr; struct net *net = sock_net(sk); struct sk_buff_head pkts; u32 dnode = tsk_peer_node(tsk); int send, sent = 0; int rc = 0; |
1d835874a tipc: Add support... |
1009 |
|
365ad353c tipc: reduce risk... |
1010 |
skb_queue_head_init(&pkts); |
7cf87fa27 tipc: return earl... |
1011 |
|
365ad353c tipc: reduce risk... |
1012 1013 |
if (unlikely(dlen > INT_MAX)) return -EMSGSIZE; |
4ccfe5e04 tipc: connection ... |
1014 |
|
365ad353c tipc: reduce risk... |
1015 1016 1017 |
/* Handle implicit connection setup */ if (unlikely(dest)) { rc = __tipc_sendmsg(sock, m, dlen); |
49984ca4e tipc: fix flow co... |
1018 1019 |
if (dlen && dlen == rc) { tsk->peer_caps = tipc_node_get_capabilities(net, dnode); |
365ad353c tipc: reduce risk... |
1020 |
tsk->snt_unacked = tsk_inc(tsk, dlen + msg_hdr_sz(hdr)); |
49984ca4e tipc: fix flow co... |
1021 |
} |
39a0295f9 tipc: Don't use i... |
1022 |
return rc; |
365ad353c tipc: reduce risk... |
1023 |
} |
f214fc402 tipc: Revert "tip... |
1024 |
|
c43072852 [NET] TIPC: Fix w... |
1025 |
do { |
365ad353c tipc: reduce risk... |
1026 1027 |
rc = tipc_wait_for_cond(sock, &timeout, (!tsk->cong_link_cnt && |
8c44e1af1 tipc: unify tipc_... |
1028 1029 |
!tsk_conn_cong(tsk) && tipc_sk_connected(sk))); |
365ad353c tipc: reduce risk... |
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 |
if (unlikely(rc)) break; send = min_t(size_t, dlen - sent, TIPC_MAX_USER_MSG_SIZE); rc = tipc_msg_build(hdr, m, sent, send, tsk->max_pkt, &pkts); if (unlikely(rc != send)) break; rc = tipc_node_xmit(net, &pkts, dnode, tsk->portid); if (unlikely(rc == -ELINKCONG)) { tsk->cong_link_cnt = 1; rc = 0; } if (likely(!rc)) { tsk->snt_unacked += tsk_inc(tsk, send + MIN_H_SIZE); sent += send; } } while (sent < dlen && !rc); |
39a0295f9 tipc: Don't use i... |
1048 |
|
3364d61c9 tipc: fix socket ... |
1049 |
return sent ? sent : rc; |
b97bf3fd8 [TIPC] Initial merge |
1050 |
} |
c43072852 [NET] TIPC: Fix w... |
1051 |
/** |
4ccfe5e04 tipc: connection ... |
1052 |
* tipc_send_packet - send a connection-oriented message |
b97bf3fd8 [TIPC] Initial merge |
1053 |
* @sock: socket structure |
4ccfe5e04 tipc: connection ... |
1054 1055 |
* @m: message to send * @dsz: length of data to be transmitted |
c43072852 [NET] TIPC: Fix w... |
1056 |
* |
4ccfe5e04 tipc: connection ... |
1057 |
* Used for SOCK_SEQPACKET messages. |
c43072852 [NET] TIPC: Fix w... |
1058 |
* |
4ccfe5e04 tipc: connection ... |
1059 |
* Returns the number of bytes sent on success, or errno otherwise |
b97bf3fd8 [TIPC] Initial merge |
1060 |
*/ |
1b7841404 net: Remove iocb ... |
1061 |
static int tipc_send_packet(struct socket *sock, struct msghdr *m, size_t dsz) |
b97bf3fd8 [TIPC] Initial merge |
1062 |
{ |
4ccfe5e04 tipc: connection ... |
1063 1064 |
if (dsz > TIPC_MAX_USER_MSG_SIZE) return -EMSGSIZE; |
b97bf3fd8 [TIPC] Initial merge |
1065 |
|
365ad353c tipc: reduce risk... |
1066 |
return tipc_sendstream(sock, m, dsz); |
b97bf3fd8 [TIPC] Initial merge |
1067 |
} |
dadebc002 tipc: eliminate p... |
1068 |
/* tipc_sk_finish_conn - complete the setup of a connection |
b97bf3fd8 [TIPC] Initial merge |
1069 |
*/ |
301bae56f tipc: merge struc... |
1070 |
static void tipc_sk_finish_conn(struct tipc_sock *tsk, u32 peer_port, |
dadebc002 tipc: eliminate p... |
1071 |
u32 peer_node) |
b97bf3fd8 [TIPC] Initial merge |
1072 |
{ |
3721e9c7c tipc: remove redu... |
1073 1074 |
struct sock *sk = &tsk->sk; struct net *net = sock_net(sk); |
301bae56f tipc: merge struc... |
1075 |
struct tipc_msg *msg = &tsk->phdr; |
b97bf3fd8 [TIPC] Initial merge |
1076 |
|
dadebc002 tipc: eliminate p... |
1077 1078 1079 1080 1081 |
msg_set_destnode(msg, peer_node); msg_set_destport(msg, peer_port); msg_set_type(msg, TIPC_CONN_MSG); msg_set_lookup_scope(msg, 0); msg_set_hdr_sz(msg, SHORT_H_SIZE); |
584d24b39 tipc: introduce n... |
1082 |
|
360aab6b4 tipc: remove prob... |
1083 |
sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL); |
8ea642ee9 tipc: create TIPC... |
1084 |
tipc_set_sk_state(sk, TIPC_ESTABLISHED); |
f2f9800d4 tipc: make tipc n... |
1085 1086 |
tipc_node_add_conn(net, peer_node, tsk->portid, peer_port); tsk->max_pkt = tipc_node_get_mtu(net, peer_node, tsk->portid); |
60020e185 tipc: propagate p... |
1087 |
tsk->peer_caps = tipc_node_get_capabilities(net, peer_node); |
10724cc7b tipc: redesign co... |
1088 1089 1090 1091 1092 1093 |
if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL) return; /* Fall back to message based flow control */ tsk->rcv_win = FLOWCTL_MSG_WIN; tsk->snd_win = FLOWCTL_MSG_WIN; |
b97bf3fd8 [TIPC] Initial merge |
1094 1095 1096 1097 1098 1099 |
} /** * set_orig_addr - capture sender's address for received message * @m: descriptor for message info * @msg: received message header |
c43072852 [NET] TIPC: Fix w... |
1100 |
* |
b97bf3fd8 [TIPC] Initial merge |
1101 1102 |
* Note: Address is not captured if not requested by receiver. */ |
05790c645 [TIPC]: Remove in... |
1103 |
static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) |
b97bf3fd8 [TIPC] Initial merge |
1104 |
{ |
342dfc306 net: add build-ti... |
1105 |
DECLARE_SOCKADDR(struct sockaddr_tipc *, addr, m->msg_name); |
b97bf3fd8 [TIPC] Initial merge |
1106 |
|
c43072852 [NET] TIPC: Fix w... |
1107 |
if (addr) { |
b97bf3fd8 [TIPC] Initial merge |
1108 1109 |
addr->family = AF_TIPC; addr->addrtype = TIPC_ADDR_ID; |
60085c3d0 tipc: fix info le... |
1110 |
memset(&addr->addr, 0, sizeof(addr->addr)); |
b97bf3fd8 [TIPC] Initial merge |
1111 1112 |
addr->addr.id.ref = msg_origport(msg); addr->addr.id.node = msg_orignode(msg); |
0e65967e3 tipc: cleanup var... |
1113 1114 |
addr->addr.name.domain = 0; /* could leave uninitialized */ addr->scope = 0; /* could leave uninitialized */ |
b97bf3fd8 [TIPC] Initial merge |
1115 1116 1117 1118 1119 |
m->msg_namelen = sizeof(struct sockaddr_tipc); } } /** |
301bae56f tipc: merge struc... |
1120 |
* tipc_sk_anc_data_recv - optionally capture ancillary data for received message |
b97bf3fd8 [TIPC] Initial merge |
1121 1122 |
* @m: descriptor for message info * @msg: received message header |
301bae56f tipc: merge struc... |
1123 |
* @tsk: TIPC port associated with message |
c43072852 [NET] TIPC: Fix w... |
1124 |
* |
b97bf3fd8 [TIPC] Initial merge |
1125 |
* Note: Ancillary data is not captured if not requested by receiver. |
c43072852 [NET] TIPC: Fix w... |
1126 |
* |
b97bf3fd8 [TIPC] Initial merge |
1127 1128 |
* Returns 0 if successful, otherwise errno */ |
301bae56f tipc: merge struc... |
1129 1130 |
static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg, struct tipc_sock *tsk) |
b97bf3fd8 [TIPC] Initial merge |
1131 1132 1133 1134 |
{ u32 anc_data[3]; u32 err; u32 dest_type; |
3546c7508 [TIPC]: Can now r... |
1135 |
int has_name; |
b97bf3fd8 [TIPC] Initial merge |
1136 1137 1138 1139 1140 1141 |
int res; if (likely(m->msg_controllen == 0)) return 0; /* Optionally capture errored message object(s) */ |
b97bf3fd8 [TIPC] Initial merge |
1142 1143 1144 1145 |
err = msg ? msg_errcode(msg) : 0; if (unlikely(err)) { anc_data[0] = err; anc_data[1] = msg_data_sz(msg); |
2db9983a4 tipc: split varia... |
1146 1147 |
res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data); if (res) |
b97bf3fd8 [TIPC] Initial merge |
1148 |
return res; |
2db9983a4 tipc: split varia... |
1149 1150 1151 1152 1153 1154 |
if (anc_data[1]) { res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], msg_data(msg)); if (res) return res; } |
b97bf3fd8 [TIPC] Initial merge |
1155 1156 1157 |
} /* Optionally capture message destination object */ |
b97bf3fd8 [TIPC] Initial merge |
1158 1159 1160 |
dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; switch (dest_type) { case TIPC_NAMED_MSG: |
3546c7508 [TIPC]: Can now r... |
1161 |
has_name = 1; |
b97bf3fd8 [TIPC] Initial merge |
1162 1163 1164 1165 1166 |
anc_data[0] = msg_nametype(msg); anc_data[1] = msg_namelower(msg); anc_data[2] = msg_namelower(msg); break; case TIPC_MCAST_MSG: |
3546c7508 [TIPC]: Can now r... |
1167 |
has_name = 1; |
b97bf3fd8 [TIPC] Initial merge |
1168 1169 1170 1171 1172 |
anc_data[0] = msg_nametype(msg); anc_data[1] = msg_namelower(msg); anc_data[2] = msg_nameupper(msg); break; case TIPC_CONN_MSG: |
301bae56f tipc: merge struc... |
1173 1174 1175 1176 |
has_name = (tsk->conn_type != 0); anc_data[0] = tsk->conn_type; anc_data[1] = tsk->conn_instance; anc_data[2] = tsk->conn_instance; |
b97bf3fd8 [TIPC] Initial merge |
1177 1178 |
break; default: |
3546c7508 [TIPC]: Can now r... |
1179 |
has_name = 0; |
b97bf3fd8 [TIPC] Initial merge |
1180 |
} |
2db9983a4 tipc: split varia... |
1181 1182 1183 1184 1185 |
if (has_name) { res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data); if (res) return res; } |
b97bf3fd8 [TIPC] Initial merge |
1186 1187 1188 |
return 0; } |
10724cc7b tipc: redesign co... |
1189 |
static void tipc_sk_send_ack(struct tipc_sock *tsk) |
739f5e4ef tipc: redefine me... |
1190 |
{ |
d6fb7e9c9 tipc: remove tsk-... |
1191 1192 |
struct sock *sk = &tsk->sk; struct net *net = sock_net(sk); |
a6ca10944 tipc: use generic... |
1193 |
struct sk_buff *skb = NULL; |
739f5e4ef tipc: redefine me... |
1194 |
struct tipc_msg *msg; |
301bae56f tipc: merge struc... |
1195 1196 |
u32 peer_port = tsk_peer_port(tsk); u32 dnode = tsk_peer_node(tsk); |
739f5e4ef tipc: redefine me... |
1197 |
|
d6fb7e9c9 tipc: remove tsk-... |
1198 |
if (!tipc_sk_connected(sk)) |
739f5e4ef tipc: redefine me... |
1199 |
return; |
c5898636c tipc: reduce usag... |
1200 1201 1202 |
skb = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE, 0, dnode, tsk_own_node(tsk), peer_port, tsk->portid, TIPC_OK); |
a6ca10944 tipc: use generic... |
1203 |
if (!skb) |
739f5e4ef tipc: redefine me... |
1204 |
return; |
a6ca10944 tipc: use generic... |
1205 |
msg = buf_msg(skb); |
10724cc7b tipc: redesign co... |
1206 1207 1208 1209 1210 1211 1212 1213 |
msg_set_conn_ack(msg, tsk->rcv_unacked); tsk->rcv_unacked = 0; /* Adjust to and advertize the correct window limit */ if (tsk->peer_caps & TIPC_BLOCK_FLOWCTL) { tsk->rcv_win = tsk_adv_blocks(tsk->sk.sk_rcvbuf); msg_set_adv_win(msg, tsk->rcv_win); } |
af9b028e2 tipc: make media ... |
1214 |
tipc_node_xmit_skb(net, skb, dnode, msg_link_selector(msg)); |
739f5e4ef tipc: redefine me... |
1215 |
} |
85d3fc941 tipc: Don't reset... |
1216 |
static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop) |
9bbb4ecc6 tipc: standardize... |
1217 1218 1219 |
{ struct sock *sk = sock->sk; DEFINE_WAIT(wait); |
85d3fc941 tipc: Don't reset... |
1220 |
long timeo = *timeop; |
4e0df4951 tipc: improve err... |
1221 1222 1223 1224 |
int err = sock_error(sk); if (err) return err; |
9bbb4ecc6 tipc: standardize... |
1225 1226 1227 |
for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
fe8e46493 tipc: avoid to un... |
1228 |
if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
6f00089c7 tipc: remove SS_D... |
1229 |
if (sk->sk_shutdown & RCV_SHUTDOWN) { |
9bbb4ecc6 tipc: standardize... |
1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 |
err = -ENOTCONN; break; } release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); } err = 0; if (!skb_queue_empty(&sk->sk_receive_queue)) break; |
9bbb4ecc6 tipc: standardize... |
1240 1241 1242 |
err = -EAGAIN; if (!timeo) break; |
143fe22f5 tipc: fix inconsi... |
1243 1244 1245 |
err = sock_intr_errno(timeo); if (signal_pending(current)) break; |
4e0df4951 tipc: improve err... |
1246 1247 1248 1249 |
err = sock_error(sk); if (err) break; |
9bbb4ecc6 tipc: standardize... |
1250 1251 |
} finish_wait(sk_sleep(sk), &wait); |
85d3fc941 tipc: Don't reset... |
1252 |
*timeop = timeo; |
9bbb4ecc6 tipc: standardize... |
1253 1254 |
return err; } |
c43072852 [NET] TIPC: Fix w... |
1255 |
/** |
247f0f3c3 tipc: align tipc ... |
1256 |
* tipc_recvmsg - receive packet-oriented message |
b97bf3fd8 [TIPC] Initial merge |
1257 |
* @m: descriptor for message info |
e9f8b1010 tipc: refactor fu... |
1258 |
* @buflen: length of user buffer area |
b97bf3fd8 [TIPC] Initial merge |
1259 |
* @flags: receive flags |
c43072852 [NET] TIPC: Fix w... |
1260 |
* |
b97bf3fd8 [TIPC] Initial merge |
1261 1262 1263 1264 1265 |
* Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages. * If the complete message doesn't fit in user area, truncate it. * * Returns size of returned message data, errno otherwise */ |
e9f8b1010 tipc: refactor fu... |
1266 1267 |
static int tipc_recvmsg(struct socket *sock, struct msghdr *m, size_t buflen, int flags) |
b97bf3fd8 [TIPC] Initial merge |
1268 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1269 |
struct sock *sk = sock->sk; |
58ed94424 tipc: align usage... |
1270 |
struct tipc_sock *tsk = tipc_sk(sk); |
e9f8b1010 tipc: refactor fu... |
1271 1272 1273 1274 1275 |
struct sk_buff *skb; struct tipc_msg *hdr; bool connected = !tipc_sk_type_connectionless(sk); int rc, err, hlen, dlen, copy; long timeout; |
b97bf3fd8 [TIPC] Initial merge |
1276 |
|
0c3141e91 [TIPC]: Overhaul ... |
1277 |
/* Catch invalid receive requests */ |
e9f8b1010 tipc: refactor fu... |
1278 |
if (unlikely(!buflen)) |
b97bf3fd8 [TIPC] Initial merge |
1279 |
return -EINVAL; |
0c3141e91 [TIPC]: Overhaul ... |
1280 |
lock_sock(sk); |
e9f8b1010 tipc: refactor fu... |
1281 1282 |
if (unlikely(connected && sk->sk_state == TIPC_OPEN)) { rc = -ENOTCONN; |
b97bf3fd8 [TIPC] Initial merge |
1283 1284 |
goto exit; } |
e9f8b1010 tipc: refactor fu... |
1285 |
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
b97bf3fd8 [TIPC] Initial merge |
1286 |
|
e9f8b1010 tipc: refactor fu... |
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 |
do { /* Look at first msg in receive queue; wait if necessary */ rc = tipc_wait_for_rcvmsg(sock, &timeout); if (unlikely(rc)) goto exit; skb = skb_peek(&sk->sk_receive_queue); hdr = buf_msg(skb); dlen = msg_data_sz(hdr); hlen = msg_hdr_sz(hdr); err = msg_errcode(hdr); if (likely(dlen || err)) break; |
2e84c60b7 tipc: remove incl... |
1299 |
tsk_advance_rx_queue(sk); |
e9f8b1010 tipc: refactor fu... |
1300 |
} while (1); |
b97bf3fd8 [TIPC] Initial merge |
1301 |
|
e9f8b1010 tipc: refactor fu... |
1302 1303 1304 1305 |
/* Collect msg meta data, including error code and rejected data */ set_orig_addr(m, hdr); rc = tipc_sk_anc_data_recv(m, hdr, tsk); if (unlikely(rc)) |
b97bf3fd8 [TIPC] Initial merge |
1306 |
goto exit; |
e9f8b1010 tipc: refactor fu... |
1307 1308 1309 1310 |
/* Capture data if non-error msg, otherwise just set return value */ if (likely(!err)) { copy = min_t(int, dlen, buflen); if (unlikely(copy != dlen)) |
b97bf3fd8 [TIPC] Initial merge |
1311 |
m->msg_flags |= MSG_TRUNC; |
e9f8b1010 tipc: refactor fu... |
1312 |
rc = skb_copy_datagram_msg(skb, hlen, m, copy); |
b97bf3fd8 [TIPC] Initial merge |
1313 |
} else { |
e9f8b1010 tipc: refactor fu... |
1314 1315 1316 1317 |
copy = 0; rc = 0; if (err != TIPC_CONN_SHUTDOWN && connected && !m->msg_control) rc = -ECONNRESET; |
b97bf3fd8 [TIPC] Initial merge |
1318 |
} |
e9f8b1010 tipc: refactor fu... |
1319 1320 |
if (unlikely(rc)) goto exit; |
b97bf3fd8 [TIPC] Initial merge |
1321 |
|
e9f8b1010 tipc: refactor fu... |
1322 |
/* Caption of data or error code/rejected data was successful */ |
10724cc7b tipc: redesign co... |
1323 1324 |
if (unlikely(flags & MSG_PEEK)) goto exit; |
10724cc7b tipc: redesign co... |
1325 |
tsk_advance_rx_queue(sk); |
e9f8b1010 tipc: refactor fu... |
1326 1327 1328 1329 1330 1331 1332 |
if (likely(!connected)) goto exit; /* Send connection flow control ack when applicable */ tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen); if (tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE) tipc_sk_send_ack(tsk); |
b97bf3fd8 [TIPC] Initial merge |
1333 |
exit: |
0c3141e91 [TIPC]: Overhaul ... |
1334 |
release_sock(sk); |
e9f8b1010 tipc: refactor fu... |
1335 |
return rc ? rc : copy; |
b97bf3fd8 [TIPC] Initial merge |
1336 |
} |
c43072852 [NET] TIPC: Fix w... |
1337 |
/** |
ec8a09fbb tipc: refactor fu... |
1338 |
* tipc_recvstream - receive stream-oriented data |
b97bf3fd8 [TIPC] Initial merge |
1339 |
* @m: descriptor for message info |
ec8a09fbb tipc: refactor fu... |
1340 |
* @buflen: total size of user buffer area |
b97bf3fd8 [TIPC] Initial merge |
1341 |
* @flags: receive flags |
c43072852 [NET] TIPC: Fix w... |
1342 1343 |
* * Used for SOCK_STREAM messages only. If not enough data is available |
b97bf3fd8 [TIPC] Initial merge |
1344 1345 1346 1347 |
* will optionally wait for more; never truncates data. * * Returns size of returned message data, errno otherwise */ |
ec8a09fbb tipc: refactor fu... |
1348 1349 |
static int tipc_recvstream(struct socket *sock, struct msghdr *m, size_t buflen, int flags) |
b97bf3fd8 [TIPC] Initial merge |
1350 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1351 |
struct sock *sk = sock->sk; |
58ed94424 tipc: align usage... |
1352 |
struct tipc_sock *tsk = tipc_sk(sk); |
ec8a09fbb tipc: refactor fu... |
1353 1354 1355 1356 1357 1358 1359 |
struct sk_buff *skb; struct tipc_msg *hdr; struct tipc_skb_cb *skb_cb; bool peek = flags & MSG_PEEK; int offset, required, copy, copied = 0; int hlen, dlen, err, rc; long timeout; |
b97bf3fd8 [TIPC] Initial merge |
1360 |
|
0c3141e91 [TIPC]: Overhaul ... |
1361 |
/* Catch invalid receive attempts */ |
ec8a09fbb tipc: refactor fu... |
1362 |
if (unlikely(!buflen)) |
b97bf3fd8 [TIPC] Initial merge |
1363 |
return -EINVAL; |
0c3141e91 [TIPC]: Overhaul ... |
1364 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1365 |
|
438adcaf0 tipc: create TIPC... |
1366 |
if (unlikely(sk->sk_state == TIPC_OPEN)) { |
ec8a09fbb tipc: refactor fu... |
1367 |
rc = -ENOTCONN; |
9bbb4ecc6 tipc: standardize... |
1368 |
goto exit; |
b97bf3fd8 [TIPC] Initial merge |
1369 |
} |
ec8a09fbb tipc: refactor fu... |
1370 1371 |
required = sock_rcvlowat(sk, flags & MSG_WAITALL, buflen); timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); |
b97bf3fd8 [TIPC] Initial merge |
1372 |
|
ec8a09fbb tipc: refactor fu... |
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 |
do { /* Look at first msg in receive queue; wait if necessary */ rc = tipc_wait_for_rcvmsg(sock, &timeout); if (unlikely(rc)) break; skb = skb_peek(&sk->sk_receive_queue); skb_cb = TIPC_SKB_CB(skb); hdr = buf_msg(skb); dlen = msg_data_sz(hdr); hlen = msg_hdr_sz(hdr); err = msg_errcode(hdr); |
0232fd0ac tipc: Allow recei... |
1384 |
|
ec8a09fbb tipc: refactor fu... |
1385 1386 1387 1388 1389 |
/* Discard any empty non-errored (SYN-) message */ if (unlikely(!dlen && !err)) { tsk_advance_rx_queue(sk); continue; } |
0232fd0ac tipc: Allow recei... |
1390 |
|
ec8a09fbb tipc: refactor fu... |
1391 1392 1393 1394 1395 1396 1397 |
/* Collect msg meta data, incl. error code and rejected data */ if (!copied) { set_orig_addr(m, hdr); rc = tipc_sk_anc_data_recv(m, hdr, tsk); if (rc) break; } |
b97bf3fd8 [TIPC] Initial merge |
1398 |
|
ec8a09fbb tipc: refactor fu... |
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 |
/* Copy data if msg ok, otherwise return error/partial data */ if (likely(!err)) { offset = skb_cb->bytes_read; copy = min_t(int, dlen - offset, buflen - copied); rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy); if (unlikely(rc)) break; copied += copy; offset += copy; if (unlikely(offset < dlen)) { if (!peek) skb_cb->bytes_read = offset; break; } } else { rc = 0; if ((err != TIPC_CONN_SHUTDOWN) && !m->msg_control) rc = -ECONNRESET; if (copied || rc) break; |
b97bf3fd8 [TIPC] Initial merge |
1419 |
} |
b97bf3fd8 [TIPC] Initial merge |
1420 |
|
ec8a09fbb tipc: refactor fu... |
1421 1422 |
if (unlikely(peek)) break; |
b97bf3fd8 [TIPC] Initial merge |
1423 |
|
ec8a09fbb tipc: refactor fu... |
1424 |
tsk_advance_rx_queue(sk); |
10724cc7b tipc: redesign co... |
1425 |
|
ec8a09fbb tipc: refactor fu... |
1426 1427 1428 1429 |
/* Send connection flow control advertisement when applicable */ tsk->rcv_unacked += tsk_inc(tsk, hlen + dlen); if (unlikely(tsk->rcv_unacked >= tsk->rcv_win / TIPC_ACK_RATE)) tipc_sk_send_ack(tsk); |
b97bf3fd8 [TIPC] Initial merge |
1430 |
|
ec8a09fbb tipc: refactor fu... |
1431 1432 1433 |
/* Exit if all requested data or FIN/error received */ if (copied == buflen || err) break; |
b97bf3fd8 [TIPC] Initial merge |
1434 |
|
ec8a09fbb tipc: refactor fu... |
1435 |
} while (!skb_queue_empty(&sk->sk_receive_queue) || copied < required); |
b97bf3fd8 [TIPC] Initial merge |
1436 |
exit: |
0c3141e91 [TIPC]: Overhaul ... |
1437 |
release_sock(sk); |
ec8a09fbb tipc: refactor fu... |
1438 |
return copied ? copied : rc; |
b97bf3fd8 [TIPC] Initial merge |
1439 1440 1441 |
} /** |
f288bef46 tipc: fix race/in... |
1442 1443 1444 1445 1446 1447 1448 1449 1450 |
* tipc_write_space - wake up thread if port congestion is released * @sk: socket */ static void tipc_write_space(struct sock *sk) { struct socket_wq *wq; rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); |
1ce0bf50a net: Generalise w... |
1451 |
if (skwq_has_sleeper(wq)) |
f288bef46 tipc: fix race/in... |
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 |
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT | POLLWRNORM | POLLWRBAND); rcu_read_unlock(); } /** * tipc_data_ready - wake up threads to indicate messages have been received * @sk: socket * @len: the length of messages */ |
676d23690 net: Fix use afte... |
1462 |
static void tipc_data_ready(struct sock *sk) |
f288bef46 tipc: fix race/in... |
1463 1464 1465 1466 1467 |
{ struct socket_wq *wq; rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); |
1ce0bf50a net: Generalise w... |
1468 |
if (skwq_has_sleeper(wq)) |
f288bef46 tipc: fix race/in... |
1469 1470 1471 1472 |
wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLRDNORM | POLLRDBAND); rcu_read_unlock(); } |
f4195d1ea tipc: avoid packe... |
1473 1474 1475 1476 |
static void tipc_sock_destruct(struct sock *sk) { __skb_queue_purge(&sk->sk_receive_queue); } |
f288bef46 tipc: fix race/in... |
1477 |
/** |
7e6c131e1 tipc: consolidate... |
1478 |
* filter_connect - Handle all incoming messages for a connection-based socket |
58ed94424 tipc: align usage... |
1479 |
* @tsk: TIPC socket |
1186adf7d tipc: simplify me... |
1480 |
* @skb: pointer to message buffer. Set to NULL if buffer is consumed |
7e6c131e1 tipc: consolidate... |
1481 |
* |
cda3696d3 tipc: clean up so... |
1482 |
* Returns true if everything ok, false otherwise |
7e6c131e1 tipc: consolidate... |
1483 |
*/ |
cda3696d3 tipc: clean up so... |
1484 |
static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb) |
7e6c131e1 tipc: consolidate... |
1485 |
{ |
58ed94424 tipc: align usage... |
1486 |
struct sock *sk = &tsk->sk; |
f2f9800d4 tipc: make tipc n... |
1487 |
struct net *net = sock_net(sk); |
cda3696d3 tipc: clean up so... |
1488 |
struct tipc_msg *hdr = buf_msg(skb); |
4e0df4951 tipc: improve err... |
1489 1490 |
u32 pport = msg_origport(hdr); u32 pnode = msg_orignode(hdr); |
7e6c131e1 tipc: consolidate... |
1491 |
|
cda3696d3 tipc: clean up so... |
1492 1493 |
if (unlikely(msg_mcast(hdr))) return false; |
7e6c131e1 tipc: consolidate... |
1494 |
|
99a208898 tipc: create TIPC... |
1495 1496 |
switch (sk->sk_state) { case TIPC_CONNECTING: |
cda3696d3 tipc: clean up so... |
1497 |
/* Accept only ACK or NACK message */ |
4e0df4951 tipc: improve err... |
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 |
if (unlikely(!msg_connected(hdr))) { if (pport != tsk_peer_port(tsk) || pnode != tsk_peer_node(tsk)) return false; tipc_set_sk_state(sk, TIPC_DISCONNECTING); sk->sk_err = ECONNREFUSED; sk->sk_state_change(sk); return true; } |
dadebc002 tipc: eliminate p... |
1508 |
|
cda3696d3 tipc: clean up so... |
1509 |
if (unlikely(msg_errcode(hdr))) { |
9fd4b070f tipc: create TIPC... |
1510 |
tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
2c8d85182 tipc: set sk_err ... |
1511 |
sk->sk_err = ECONNREFUSED; |
4e0df4951 tipc: improve err... |
1512 |
sk->sk_state_change(sk); |
cda3696d3 tipc: clean up so... |
1513 |
return true; |
584d24b39 tipc: introduce n... |
1514 |
} |
cda3696d3 tipc: clean up so... |
1515 |
if (unlikely(!msg_isdata(hdr))) { |
9fd4b070f tipc: create TIPC... |
1516 |
tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
dadebc002 tipc: eliminate p... |
1517 |
sk->sk_err = EINVAL; |
4e0df4951 tipc: improve err... |
1518 |
sk->sk_state_change(sk); |
cda3696d3 tipc: clean up so... |
1519 |
return true; |
584d24b39 tipc: introduce n... |
1520 |
} |
cda3696d3 tipc: clean up so... |
1521 1522 |
tipc_sk_finish_conn(tsk, msg_origport(hdr), msg_orignode(hdr)); msg_set_importance(&tsk->phdr, msg_importance(hdr)); |
dadebc002 tipc: eliminate p... |
1523 |
|
cda3696d3 tipc: clean up so... |
1524 1525 1526 1527 1528 |
/* If 'ACK+' message, add to socket receive queue */ if (msg_data_sz(hdr)) return true; /* If empty 'ACK-' message, wake up sleeping connect() */ |
42b531de1 tipc: Fix missing... |
1529 |
sk->sk_data_ready(sk); |
cda3696d3 tipc: clean up so... |
1530 1531 1532 1533 |
/* 'ACK-' message is neither accepted nor rejected: */ msg_set_dest_droppable(hdr, 1); return false; |
cda3696d3 tipc: clean up so... |
1534 |
|
438adcaf0 tipc: create TIPC... |
1535 |
case TIPC_OPEN: |
9fd4b070f tipc: create TIPC... |
1536 |
case TIPC_DISCONNECTING: |
438adcaf0 tipc: create TIPC... |
1537 1538 |
break; case TIPC_LISTEN: |
7e6c131e1 tipc: consolidate... |
1539 |
/* Accept only SYN message */ |
cda3696d3 tipc: clean up so... |
1540 1541 |
if (!msg_connected(hdr) && !(msg_errcode(hdr))) return true; |
7e6c131e1 tipc: consolidate... |
1542 |
break; |
f40acbaf4 tipc: remove SS_C... |
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 |
case TIPC_ESTABLISHED: /* Accept only connection-based messages sent by peer */ if (unlikely(!tsk_peer_msg(tsk, hdr))) return false; if (unlikely(msg_errcode(hdr))) { tipc_set_sk_state(sk, TIPC_DISCONNECTING); /* Let timer expire on it's own */ tipc_node_remove_conn(net, tsk_peer_node(tsk), tsk->portid); sk->sk_state_change(sk); } return true; |
7e6c131e1 tipc: consolidate... |
1556 |
default: |
438adcaf0 tipc: create TIPC... |
1557 1558 |
pr_err("Unknown sk_state %u ", sk->sk_state); |
7e6c131e1 tipc: consolidate... |
1559 |
} |
438adcaf0 tipc: create TIPC... |
1560 |
|
cda3696d3 tipc: clean up so... |
1561 |
return false; |
7e6c131e1 tipc: consolidate... |
1562 1563 1564 |
} /** |
aba79f332 tipc: byte-based ... |
1565 1566 |
* rcvbuf_limit - get proper overload limit of socket receive queue * @sk: socket |
10724cc7b tipc: redesign co... |
1567 |
* @skb: message |
aba79f332 tipc: byte-based ... |
1568 |
* |
10724cc7b tipc: redesign co... |
1569 1570 |
* For connection oriented messages, irrespective of importance, * default queue limit is 2 MB. |
aba79f332 tipc: byte-based ... |
1571 |
* |
10724cc7b tipc: redesign co... |
1572 1573 |
* For connectionless messages, queue limits are based on message * importance as follows: |
aba79f332 tipc: byte-based ... |
1574 |
* |
10724cc7b tipc: redesign co... |
1575 1576 1577 1578 |
* TIPC_LOW_IMPORTANCE (2 MB) * TIPC_MEDIUM_IMPORTANCE (4 MB) * TIPC_HIGH_IMPORTANCE (8 MB) * TIPC_CRITICAL_IMPORTANCE (16 MB) |
aba79f332 tipc: byte-based ... |
1579 1580 1581 |
* * Returns overload limit according to corresponding message importance */ |
10724cc7b tipc: redesign co... |
1582 |
static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *skb) |
aba79f332 tipc: byte-based ... |
1583 |
{ |
10724cc7b tipc: redesign co... |
1584 1585 1586 1587 1588 |
struct tipc_sock *tsk = tipc_sk(sk); struct tipc_msg *hdr = buf_msg(skb); if (unlikely(!msg_connected(hdr))) return sk->sk_rcvbuf << msg_importance(hdr); |
aba79f332 tipc: byte-based ... |
1589 |
|
10724cc7b tipc: redesign co... |
1590 1591 |
if (likely(tsk->peer_caps & TIPC_BLOCK_FLOWCTL)) return sk->sk_rcvbuf; |
0cee6bbe0 tipc: remove unne... |
1592 |
|
10724cc7b tipc: redesign co... |
1593 |
return FLOWCTL_MSG_LIM; |
aba79f332 tipc: byte-based ... |
1594 1595 1596 |
} /** |
0c3141e91 [TIPC]: Overhaul ... |
1597 1598 |
* filter_rcv - validate incoming message * @sk: socket |
cda3696d3 tipc: clean up so... |
1599 |
* @skb: pointer to message. |
c43072852 [NET] TIPC: Fix w... |
1600 |
* |
0c3141e91 [TIPC]: Overhaul ... |
1601 1602 1603 |
* Enqueues message on receive queue if acceptable; optionally handles * disconnect indication for a connected socket. * |
1186adf7d tipc: simplify me... |
1604 |
* Called with socket lock already taken |
c43072852 [NET] TIPC: Fix w... |
1605 |
* |
cda3696d3 tipc: clean up so... |
1606 |
* Returns true if message was added to socket receive queue, otherwise false |
b97bf3fd8 [TIPC] Initial merge |
1607 |
*/ |
f1d048f24 tipc: fix socket ... |
1608 1609 |
static bool filter_rcv(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *xmitq) |
b97bf3fd8 [TIPC] Initial merge |
1610 |
{ |
58ed94424 tipc: align usage... |
1611 |
struct tipc_sock *tsk = tipc_sk(sk); |
cda3696d3 tipc: clean up so... |
1612 1613 1614 1615 |
struct tipc_msg *hdr = buf_msg(skb); unsigned int limit = rcvbuf_limit(sk, skb); int err = TIPC_OK; int usr = msg_user(hdr); |
365ad353c tipc: reduce risk... |
1616 |
u32 onode; |
b97bf3fd8 [TIPC] Initial merge |
1617 |
|
cda3696d3 tipc: clean up so... |
1618 |
if (unlikely(msg_user(hdr) == CONN_MANAGER)) { |
f1d048f24 tipc: fix socket ... |
1619 |
tipc_sk_proto_rcv(tsk, skb, xmitq); |
cda3696d3 tipc: clean up so... |
1620 |
return false; |
1186adf7d tipc: simplify me... |
1621 |
} |
ec8a2e562 tipc: same receiv... |
1622 |
|
cda3696d3 tipc: clean up so... |
1623 |
if (unlikely(usr == SOCK_WAKEUP)) { |
365ad353c tipc: reduce risk... |
1624 |
onode = msg_orignode(hdr); |
cda3696d3 tipc: clean up so... |
1625 |
kfree_skb(skb); |
365ad353c tipc: reduce risk... |
1626 1627 |
u32_del(&tsk->cong_links, onode); tsk->cong_link_cnt--; |
50100a5e3 tipc: use pseudo ... |
1628 |
sk->sk_write_space(sk); |
cda3696d3 tipc: clean up so... |
1629 |
return false; |
50100a5e3 tipc: use pseudo ... |
1630 |
} |
cda3696d3 tipc: clean up so... |
1631 1632 1633 1634 1635 |
/* Drop if illegal message type */ if (unlikely(msg_type(hdr) > TIPC_DIRECT_MSG)) { kfree_skb(skb); return false; } |
0c3141e91 [TIPC]: Overhaul ... |
1636 |
|
cda3696d3 tipc: clean up so... |
1637 |
/* Reject if wrong message type for current socket state */ |
c752023aa tipc: remove sock... |
1638 |
if (tipc_sk_type_connectionless(sk)) { |
cda3696d3 tipc: clean up so... |
1639 1640 1641 1642 1643 1644 1645 |
if (msg_connected(hdr)) { err = TIPC_ERR_NO_PORT; goto reject; } } else if (unlikely(!filter_connect(tsk, skb))) { err = TIPC_ERR_NO_PORT; goto reject; |
b97bf3fd8 [TIPC] Initial merge |
1646 1647 1648 |
} /* Reject message if there isn't room to queue it */ |
cda3696d3 tipc: clean up so... |
1649 1650 1651 1652 |
if (unlikely(sk_rmem_alloc_get(sk) + skb->truesize >= limit)) { err = TIPC_ERR_OVERLOAD; goto reject; } |
b97bf3fd8 [TIPC] Initial merge |
1653 |
|
aba79f332 tipc: byte-based ... |
1654 |
/* Enqueue message */ |
ba8aebe94 tipc: rename stru... |
1655 |
TIPC_SKB_CB(skb)->bytes_read = 0; |
cda3696d3 tipc: clean up so... |
1656 1657 |
__skb_queue_tail(&sk->sk_receive_queue, skb); skb_set_owner_r(skb, sk); |
0c3141e91 [TIPC]: Overhaul ... |
1658 |
|
676d23690 net: Fix use afte... |
1659 |
sk->sk_data_ready(sk); |
cda3696d3 tipc: clean up so... |
1660 1661 1662 |
return true; reject: |
f1d048f24 tipc: fix socket ... |
1663 1664 |
if (tipc_msg_reverse(tsk_own_node(tsk), &skb, err)) __skb_queue_tail(xmitq, skb); |
cda3696d3 tipc: clean up so... |
1665 |
return false; |
0c3141e91 [TIPC]: Overhaul ... |
1666 |
} |
b97bf3fd8 [TIPC] Initial merge |
1667 |
|
0c3141e91 [TIPC]: Overhaul ... |
1668 |
/** |
4f4482dcd tipc: compensate ... |
1669 |
* tipc_backlog_rcv - handle incoming message from backlog queue |
0c3141e91 [TIPC]: Overhaul ... |
1670 |
* @sk: socket |
a6ca10944 tipc: use generic... |
1671 |
* @skb: message |
0c3141e91 [TIPC]: Overhaul ... |
1672 |
* |
e3a77561e tipc: split up fu... |
1673 |
* Caller must hold socket lock |
0c3141e91 [TIPC]: Overhaul ... |
1674 1675 1676 |
* * Returns 0 */ |
a6ca10944 tipc: use generic... |
1677 |
static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb) |
0c3141e91 [TIPC]: Overhaul ... |
1678 |
{ |
cda3696d3 tipc: clean up so... |
1679 |
unsigned int truesize = skb->truesize; |
f1d048f24 tipc: fix socket ... |
1680 1681 |
struct sk_buff_head xmitq; u32 dnode, selector; |
0c3141e91 [TIPC]: Overhaul ... |
1682 |
|
f1d048f24 tipc: fix socket ... |
1683 1684 1685 |
__skb_queue_head_init(&xmitq); if (likely(filter_rcv(sk, skb, &xmitq))) { |
cda3696d3 tipc: clean up so... |
1686 |
atomic_add(truesize, &tipc_sk(sk)->dupl_rcvcnt); |
f1d048f24 tipc: fix socket ... |
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 |
return 0; } if (skb_queue_empty(&xmitq)) return 0; /* Send response/rejected message */ skb = __skb_dequeue(&xmitq); dnode = msg_destnode(buf_msg(skb)); selector = msg_origport(buf_msg(skb)); tipc_node_xmit_skb(sock_net(sk), skb, dnode, selector); |
0c3141e91 [TIPC]: Overhaul ... |
1698 1699 1700 1701 |
return 0; } /** |
c637c1035 tipc: resolve rac... |
1702 1703 1704 1705 1706 |
* tipc_sk_enqueue - extract all buffers with destination 'dport' from * inputq and try adding them to socket or backlog queue * @inputq: list of incoming buffers with potentially different destinations * @sk: socket where the buffers should be enqueued * @dport: port number for the socket |
d570d8649 tipc: enqueue arr... |
1707 1708 |
* * Caller must hold socket lock |
d570d8649 tipc: enqueue arr... |
1709 |
*/ |
cda3696d3 tipc: clean up so... |
1710 |
static void tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk, |
f1d048f24 tipc: fix socket ... |
1711 |
u32 dport, struct sk_buff_head *xmitq) |
d570d8649 tipc: enqueue arr... |
1712 |
{ |
f1d048f24 tipc: fix socket ... |
1713 1714 |
unsigned long time_limit = jiffies + 2; struct sk_buff *skb; |
d570d8649 tipc: enqueue arr... |
1715 1716 |
unsigned int lim; atomic_t *dcnt; |
f1d048f24 tipc: fix socket ... |
1717 |
u32 onode; |
c637c1035 tipc: resolve rac... |
1718 1719 |
while (skb_queue_len(inputq)) { |
51a00daf7 tipc: fix bug in ... |
1720 |
if (unlikely(time_after_eq(jiffies, time_limit))) |
cda3696d3 tipc: clean up so... |
1721 |
return; |
c637c1035 tipc: resolve rac... |
1722 1723 |
skb = tipc_skb_dequeue(inputq, dport); if (unlikely(!skb)) |
cda3696d3 tipc: clean up so... |
1724 1725 1726 |
return; /* Add message directly to receive queue if possible */ |
c637c1035 tipc: resolve rac... |
1727 |
if (!sock_owned_by_user(sk)) { |
f1d048f24 tipc: fix socket ... |
1728 |
filter_rcv(sk, skb, xmitq); |
cda3696d3 tipc: clean up so... |
1729 |
continue; |
c637c1035 tipc: resolve rac... |
1730 |
} |
cda3696d3 tipc: clean up so... |
1731 1732 |
/* Try backlog, compensating for double-counted bytes */ |
c637c1035 tipc: resolve rac... |
1733 |
dcnt = &tipc_sk(sk)->dupl_rcvcnt; |
7c8bcfb12 tipc: re-enable c... |
1734 |
if (!sk->sk_backlog.len) |
c637c1035 tipc: resolve rac... |
1735 1736 1737 1738 |
atomic_set(dcnt, 0); lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt); if (likely(!sk_add_backlog(sk, skb, lim))) continue; |
cda3696d3 tipc: clean up so... |
1739 1740 |
/* Overload => reject message back to sender */ |
f1d048f24 tipc: fix socket ... |
1741 1742 1743 |
onode = tipc_own_addr(sock_net(sk)); if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) __skb_queue_tail(xmitq, skb); |
cda3696d3 tipc: clean up so... |
1744 |
break; |
c637c1035 tipc: resolve rac... |
1745 |
} |
d570d8649 tipc: enqueue arr... |
1746 1747 1748 |
} /** |
c637c1035 tipc: resolve rac... |
1749 1750 1751 1752 |
* tipc_sk_rcv - handle a chain of incoming buffers * @inputq: buffer list containing the buffers * Consumes all buffers in list until inputq is empty * Note: may be called in multiple threads referring to the same queue |
0c3141e91 [TIPC]: Overhaul ... |
1753 |
*/ |
cda3696d3 tipc: clean up so... |
1754 |
void tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq) |
0c3141e91 [TIPC]: Overhaul ... |
1755 |
{ |
f1d048f24 tipc: fix socket ... |
1756 |
struct sk_buff_head xmitq; |
c637c1035 tipc: resolve rac... |
1757 |
u32 dnode, dport = 0; |
9871b27f6 tipc: fix random ... |
1758 |
int err; |
9816f0615 tipc: merge port ... |
1759 |
struct tipc_sock *tsk; |
9816f0615 tipc: merge port ... |
1760 |
struct sock *sk; |
cda3696d3 tipc: clean up so... |
1761 |
struct sk_buff *skb; |
9816f0615 tipc: merge port ... |
1762 |
|
f1d048f24 tipc: fix socket ... |
1763 |
__skb_queue_head_init(&xmitq); |
c637c1035 tipc: resolve rac... |
1764 |
while (skb_queue_len(inputq)) { |
c637c1035 tipc: resolve rac... |
1765 1766 |
dport = tipc_skb_peek_port(inputq, dport); tsk = tipc_sk_lookup(net, dport); |
cda3696d3 tipc: clean up so... |
1767 |
|
c637c1035 tipc: resolve rac... |
1768 1769 1770 |
if (likely(tsk)) { sk = &tsk->sk; if (likely(spin_trylock_bh(&sk->sk_lock.slock))) { |
f1d048f24 tipc: fix socket ... |
1771 |
tipc_sk_enqueue(inputq, sk, dport, &xmitq); |
c637c1035 tipc: resolve rac... |
1772 |
spin_unlock_bh(&sk->sk_lock.slock); |
c637c1035 tipc: resolve rac... |
1773 |
} |
f1d048f24 tipc: fix socket ... |
1774 1775 1776 1777 1778 |
/* Send pending response/rejected messages, if any */ while ((skb = __skb_dequeue(&xmitq))) { dnode = msg_destnode(buf_msg(skb)); tipc_node_xmit_skb(net, skb, dnode, dport); } |
c637c1035 tipc: resolve rac... |
1779 |
sock_put(sk); |
c637c1035 tipc: resolve rac... |
1780 |
continue; |
c637c1035 tipc: resolve rac... |
1781 |
} |
cda3696d3 tipc: clean up so... |
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 |
/* No destination socket => dequeue skb if still there */ skb = tipc_skb_dequeue(inputq, dport); if (!skb) return; /* Try secondary lookup if unresolved named message */ err = TIPC_ERR_NO_PORT; if (tipc_msg_lookup_dest(net, skb, &err)) goto xmit; /* Prepare for message rejection */ if (!tipc_msg_reverse(tipc_own_addr(net), &skb, err)) |
c637c1035 tipc: resolve rac... |
1795 |
continue; |
e3a77561e tipc: split up fu... |
1796 |
xmit: |
cda3696d3 tipc: clean up so... |
1797 |
dnode = msg_destnode(buf_msg(skb)); |
af9b028e2 tipc: make media ... |
1798 |
tipc_node_xmit_skb(net, skb, dnode, dport); |
c637c1035 tipc: resolve rac... |
1799 |
} |
b97bf3fd8 [TIPC] Initial merge |
1800 |
} |
78eb3a537 tipc: standardize... |
1801 1802 |
static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) { |
d9dc8b0f8 net: fix sleeping... |
1803 |
DEFINE_WAIT_FUNC(wait, woken_wake_function); |
78eb3a537 tipc: standardize... |
1804 |
struct sock *sk = sock->sk; |
78eb3a537 tipc: standardize... |
1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 |
int done; do { int err = sock_error(sk); if (err) return err; if (!*timeo_p) return -ETIMEDOUT; if (signal_pending(current)) return sock_intr_errno(*timeo_p); |
d9dc8b0f8 net: fix sleeping... |
1815 |
add_wait_queue(sk_sleep(sk), &wait); |
99a208898 tipc: create TIPC... |
1816 |
done = sk_wait_event(sk, timeo_p, |
d9dc8b0f8 net: fix sleeping... |
1817 1818 |
sk->sk_state != TIPC_CONNECTING, &wait); remove_wait_queue(sk_sleep(sk), &wait); |
78eb3a537 tipc: standardize... |
1819 1820 1821 |
} while (!done); return 0; } |
b97bf3fd8 [TIPC] Initial merge |
1822 |
/** |
247f0f3c3 tipc: align tipc ... |
1823 |
* tipc_connect - establish a connection to another TIPC port |
b97bf3fd8 [TIPC] Initial merge |
1824 1825 1826 |
* @sock: socket structure * @dest: socket address for destination port * @destlen: size of socket address data structure |
0c3141e91 [TIPC]: Overhaul ... |
1827 |
* @flags: file-related flags associated with socket |
b97bf3fd8 [TIPC] Initial merge |
1828 1829 1830 |
* * Returns 0 on success, errno otherwise */ |
247f0f3c3 tipc: align tipc ... |
1831 1832 |
static int tipc_connect(struct socket *sock, struct sockaddr *dest, int destlen, int flags) |
b97bf3fd8 [TIPC] Initial merge |
1833 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1834 |
struct sock *sk = sock->sk; |
f2f8036e3 tipc: add support... |
1835 |
struct tipc_sock *tsk = tipc_sk(sk); |
b89741a0c [TIPC]: Cosmetic ... |
1836 1837 |
struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; struct msghdr m = {NULL,}; |
f2f8036e3 tipc: add support... |
1838 |
long timeout = (flags & O_NONBLOCK) ? 0 : tsk->conn_timeout; |
99a208898 tipc: create TIPC... |
1839 |
int previous; |
f2f8036e3 tipc: add support... |
1840 |
int res = 0; |
b89741a0c [TIPC]: Cosmetic ... |
1841 |
|
0c3141e91 [TIPC]: Overhaul ... |
1842 |
lock_sock(sk); |
f2f8036e3 tipc: add support... |
1843 |
/* DGRAM/RDM connect(), just save the destaddr */ |
c752023aa tipc: remove sock... |
1844 |
if (tipc_sk_type_connectionless(sk)) { |
f2f8036e3 tipc: add support... |
1845 |
if (dst->family == AF_UNSPEC) { |
aeda16b6a tipc: rename tsk-... |
1846 |
memset(&tsk->peer, 0, sizeof(struct sockaddr_tipc)); |
610600c8c tipc: validate le... |
1847 1848 |
} else if (destlen != sizeof(struct sockaddr_tipc)) { res = -EINVAL; |
f2f8036e3 tipc: add support... |
1849 |
} else { |
aeda16b6a tipc: rename tsk-... |
1850 |
memcpy(&tsk->peer, dest, destlen); |
f2f8036e3 tipc: add support... |
1851 |
} |
0c3141e91 [TIPC]: Overhaul ... |
1852 1853 |
goto exit; } |
b89741a0c [TIPC]: Cosmetic ... |
1854 |
|
b89741a0c [TIPC]: Cosmetic ... |
1855 1856 1857 1858 1859 1860 |
/* * Reject connection attempt using multicast address * * Note: send_msg() validates the rest of the address fields, * so there's no need to do it here */ |
0c3141e91 [TIPC]: Overhaul ... |
1861 1862 1863 1864 |
if (dst->addrtype == TIPC_ADDR_MCAST) { res = -EINVAL; goto exit; } |
99a208898 tipc: create TIPC... |
1865 |
previous = sk->sk_state; |
438adcaf0 tipc: create TIPC... |
1866 1867 1868 |
switch (sk->sk_state) { case TIPC_OPEN: |
584d24b39 tipc: introduce n... |
1869 1870 1871 1872 1873 1874 1875 1876 1877 |
/* Send a 'SYN-' to destination */ m.msg_name = dest; m.msg_namelen = destlen; /* If connect is in non-blocking case, set MSG_DONTWAIT to * indicate send_msg() is never blocked. */ if (!timeout) m.msg_flags = MSG_DONTWAIT; |
39a0295f9 tipc: Don't use i... |
1878 |
res = __tipc_sendmsg(sock, &m, 0); |
584d24b39 tipc: introduce n... |
1879 1880 |
if ((res < 0) && (res != -EWOULDBLOCK)) goto exit; |
99a208898 tipc: create TIPC... |
1881 |
/* Just entered TIPC_CONNECTING state; the only |
584d24b39 tipc: introduce n... |
1882 1883 1884 1885 |
* difference is that return value in non-blocking * case is EINPROGRESS, rather than EALREADY. */ res = -EINPROGRESS; |
99a208898 tipc: create TIPC... |
1886 1887 1888 1889 1890 |
/* fall thru' */ case TIPC_CONNECTING: if (!timeout) { if (previous == TIPC_CONNECTING) res = -EALREADY; |
78eb3a537 tipc: standardize... |
1891 |
goto exit; |
99a208898 tipc: create TIPC... |
1892 |
} |
78eb3a537 tipc: standardize... |
1893 1894 1895 |
timeout = msecs_to_jiffies(timeout); /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ res = tipc_wait_for_connect(sock, &timeout); |
f40acbaf4 tipc: remove SS_C... |
1896 1897 |
break; case TIPC_ESTABLISHED: |
584d24b39 tipc: introduce n... |
1898 |
res = -EISCONN; |
f40acbaf4 tipc: remove SS_C... |
1899 1900 |
break; default: |
584d24b39 tipc: introduce n... |
1901 |
res = -EINVAL; |
f40acbaf4 tipc: remove SS_C... |
1902 |
} |
99a208898 tipc: create TIPC... |
1903 |
|
0c3141e91 [TIPC]: Overhaul ... |
1904 1905 |
exit: release_sock(sk); |
b89741a0c [TIPC]: Cosmetic ... |
1906 |
return res; |
b97bf3fd8 [TIPC] Initial merge |
1907 |
} |
c43072852 [NET] TIPC: Fix w... |
1908 |
/** |
247f0f3c3 tipc: align tipc ... |
1909 |
* tipc_listen - allow socket to listen for incoming connections |
b97bf3fd8 [TIPC] Initial merge |
1910 1911 |
* @sock: socket structure * @len: (unused) |
c43072852 [NET] TIPC: Fix w... |
1912 |
* |
b97bf3fd8 [TIPC] Initial merge |
1913 1914 |
* Returns 0 on success, errno otherwise */ |
247f0f3c3 tipc: align tipc ... |
1915 |
static int tipc_listen(struct socket *sock, int len) |
b97bf3fd8 [TIPC] Initial merge |
1916 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
1917 1918 1919 1920 |
struct sock *sk = sock->sk; int res; lock_sock(sk); |
0c288c869 tipc: create TIPC... |
1921 |
res = tipc_set_sk_state(sk, TIPC_LISTEN); |
0c3141e91 [TIPC]: Overhaul ... |
1922 |
release_sock(sk); |
0c288c869 tipc: create TIPC... |
1923 |
|
0c3141e91 [TIPC]: Overhaul ... |
1924 |
return res; |
b97bf3fd8 [TIPC] Initial merge |
1925 |
} |
6398e23cd tipc: standardize... |
1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 |
static int tipc_wait_for_accept(struct socket *sock, long timeo) { struct sock *sk = sock->sk; DEFINE_WAIT(wait); int err; /* True wake-one mechanism for incoming connections: only * one process gets woken up, not the 'whole herd'. * Since we do not 'race & poll' for established sockets * anymore, the common case will execute the loop only once. */ for (;;) { prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
fe8e46493 tipc: avoid to un... |
1940 |
if (timeo && skb_queue_empty(&sk->sk_receive_queue)) { |
6398e23cd tipc: standardize... |
1941 1942 1943 1944 1945 1946 1947 |
release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); } err = 0; if (!skb_queue_empty(&sk->sk_receive_queue)) break; |
6398e23cd tipc: standardize... |
1948 1949 1950 |
err = -EAGAIN; if (!timeo) break; |
143fe22f5 tipc: fix inconsi... |
1951 1952 1953 |
err = sock_intr_errno(timeo); if (signal_pending(current)) break; |
6398e23cd tipc: standardize... |
1954 1955 1956 1957 |
} finish_wait(sk_sleep(sk), &wait); return err; } |
c43072852 [NET] TIPC: Fix w... |
1958 |
/** |
247f0f3c3 tipc: align tipc ... |
1959 |
* tipc_accept - wait for connection request |
b97bf3fd8 [TIPC] Initial merge |
1960 1961 1962 |
* @sock: listening socket * @newsock: new socket that is to be connected * @flags: file-related flags associated with socket |
c43072852 [NET] TIPC: Fix w... |
1963 |
* |
b97bf3fd8 [TIPC] Initial merge |
1964 1965 |
* Returns 0 on success, errno otherwise */ |
cdfbabfb2 net: Work around ... |
1966 1967 |
static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags, bool kern) |
b97bf3fd8 [TIPC] Initial merge |
1968 |
{ |
0fef8f205 tipc: refactor ac... |
1969 |
struct sock *new_sk, *sk = sock->sk; |
b97bf3fd8 [TIPC] Initial merge |
1970 |
struct sk_buff *buf; |
301bae56f tipc: merge struc... |
1971 |
struct tipc_sock *new_tsock; |
0fef8f205 tipc: refactor ac... |
1972 |
struct tipc_msg *msg; |
6398e23cd tipc: standardize... |
1973 |
long timeo; |
0c3141e91 [TIPC]: Overhaul ... |
1974 |
int res; |
b97bf3fd8 [TIPC] Initial merge |
1975 |
|
0c3141e91 [TIPC]: Overhaul ... |
1976 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
1977 |
|
0c288c869 tipc: create TIPC... |
1978 |
if (sk->sk_state != TIPC_LISTEN) { |
0c3141e91 [TIPC]: Overhaul ... |
1979 |
res = -EINVAL; |
b97bf3fd8 [TIPC] Initial merge |
1980 1981 |
goto exit; } |
6398e23cd tipc: standardize... |
1982 1983 1984 1985 |
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); res = tipc_wait_for_accept(sock, timeo); if (res) goto exit; |
0c3141e91 [TIPC]: Overhaul ... |
1986 1987 |
buf = skb_peek(&sk->sk_receive_queue); |
cdfbabfb2 net: Work around ... |
1988 |
res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, kern); |
0fef8f205 tipc: refactor ac... |
1989 1990 |
if (res) goto exit; |
fdd75ea8d net/tipc: initial... |
1991 |
security_sk_clone(sock->sk, new_sock->sk); |
b97bf3fd8 [TIPC] Initial merge |
1992 |
|
0fef8f205 tipc: refactor ac... |
1993 |
new_sk = new_sock->sk; |
301bae56f tipc: merge struc... |
1994 |
new_tsock = tipc_sk(new_sk); |
0fef8f205 tipc: refactor ac... |
1995 |
msg = buf_msg(buf); |
b97bf3fd8 [TIPC] Initial merge |
1996 |
|
0fef8f205 tipc: refactor ac... |
1997 1998 1999 2000 2001 2002 2003 |
/* we lock on new_sk; but lockdep sees the lock on sk */ lock_sock_nested(new_sk, SINGLE_DEPTH_NESTING); /* * Reject any stray messages received by new socket * before the socket lock was taken (very, very unlikely) */ |
2e84c60b7 tipc: remove incl... |
2004 |
tsk_rej_rx_queue(new_sk); |
0fef8f205 tipc: refactor ac... |
2005 2006 |
/* Connect new socket to it's peer */ |
301bae56f tipc: merge struc... |
2007 |
tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg)); |
0fef8f205 tipc: refactor ac... |
2008 |
|
301bae56f tipc: merge struc... |
2009 |
tsk_set_importance(new_tsock, msg_importance(msg)); |
0fef8f205 tipc: refactor ac... |
2010 |
if (msg_named(msg)) { |
301bae56f tipc: merge struc... |
2011 2012 |
new_tsock->conn_type = msg_nametype(msg); new_tsock->conn_instance = msg_nameinst(msg); |
b97bf3fd8 [TIPC] Initial merge |
2013 |
} |
0fef8f205 tipc: refactor ac... |
2014 2015 2016 2017 2018 2019 2020 |
/* * Respond to 'SYN-' by discarding it & returning 'ACK'-. * Respond to 'SYN+' by queuing it on new socket. */ if (!msg_data_sz(msg)) { struct msghdr m = {NULL,}; |
2e84c60b7 tipc: remove incl... |
2021 |
tsk_advance_rx_queue(sk); |
365ad353c tipc: reduce risk... |
2022 |
__tipc_sendstream(new_sock, &m, 0); |
0fef8f205 tipc: refactor ac... |
2023 2024 2025 |
} else { __skb_dequeue(&sk->sk_receive_queue); __skb_queue_head(&new_sk->sk_receive_queue, buf); |
aba79f332 tipc: byte-based ... |
2026 |
skb_set_owner_r(buf, new_sk); |
0fef8f205 tipc: refactor ac... |
2027 2028 |
} release_sock(new_sk); |
b97bf3fd8 [TIPC] Initial merge |
2029 |
exit: |
0c3141e91 [TIPC]: Overhaul ... |
2030 |
release_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
2031 2032 2033 2034 |
return res; } /** |
247f0f3c3 tipc: align tipc ... |
2035 |
* tipc_shutdown - shutdown socket connection |
b97bf3fd8 [TIPC] Initial merge |
2036 |
* @sock: socket structure |
e247a8f5d [TIPC]: Add argum... |
2037 |
* @how: direction to close (must be SHUT_RDWR) |
b97bf3fd8 [TIPC] Initial merge |
2038 2039 |
* * Terminates connection (if necessary), then purges socket's receive queue. |
c43072852 [NET] TIPC: Fix w... |
2040 |
* |
b97bf3fd8 [TIPC] Initial merge |
2041 2042 |
* Returns 0 on success, errno otherwise */ |
247f0f3c3 tipc: align tipc ... |
2043 |
static int tipc_shutdown(struct socket *sock, int how) |
b97bf3fd8 [TIPC] Initial merge |
2044 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
2045 |
struct sock *sk = sock->sk; |
b97bf3fd8 [TIPC] Initial merge |
2046 |
int res; |
e247a8f5d [TIPC]: Add argum... |
2047 2048 |
if (how != SHUT_RDWR) return -EINVAL; |
b97bf3fd8 [TIPC] Initial merge |
2049 |
|
0c3141e91 [TIPC]: Overhaul ... |
2050 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
2051 |
|
6f00089c7 tipc: remove SS_D... |
2052 2053 |
__tipc_shutdown(sock, TIPC_CONN_SHUTDOWN); sk->sk_shutdown = SEND_SHUTDOWN; |
b97bf3fd8 [TIPC] Initial merge |
2054 |
|
6f00089c7 tipc: remove SS_D... |
2055 |
if (sk->sk_state == TIPC_DISCONNECTING) { |
750311510 tipc: wake up all... |
2056 |
/* Discard any unreceived messages */ |
57467e562 tipc: eliminate d... |
2057 |
__skb_queue_purge(&sk->sk_receive_queue); |
750311510 tipc: wake up all... |
2058 2059 2060 |
/* Wake up anyone sleeping in poll */ sk->sk_state_change(sk); |
b97bf3fd8 [TIPC] Initial merge |
2061 |
res = 0; |
6f00089c7 tipc: remove SS_D... |
2062 |
} else { |
b97bf3fd8 [TIPC] Initial merge |
2063 2064 |
res = -ENOTCONN; } |
0c3141e91 [TIPC]: Overhaul ... |
2065 |
release_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
2066 2067 |
return res; } |
f2f2a96a2 tipc: feed tipc s... |
2068 |
static void tipc_sk_timeout(unsigned long data) |
572890158 tipc: clean up so... |
2069 |
{ |
f2f2a96a2 tipc: feed tipc s... |
2070 2071 |
struct tipc_sock *tsk = (struct tipc_sock *)data; struct sock *sk = &tsk->sk; |
a6ca10944 tipc: use generic... |
2072 |
struct sk_buff *skb = NULL; |
572890158 tipc: clean up so... |
2073 |
u32 peer_port, peer_node; |
c5898636c tipc: reduce usag... |
2074 |
u32 own_node = tsk_own_node(tsk); |
572890158 tipc: clean up so... |
2075 |
|
6c9808ce0 tipc: remove port... |
2076 |
bh_lock_sock(sk); |
d6fb7e9c9 tipc: remove tsk-... |
2077 |
if (!tipc_sk_connected(sk)) { |
6c9808ce0 tipc: remove port... |
2078 2079 |
bh_unlock_sock(sk); goto exit; |
572890158 tipc: clean up so... |
2080 |
} |
301bae56f tipc: merge struc... |
2081 2082 |
peer_port = tsk_peer_port(tsk); peer_node = tsk_peer_node(tsk); |
572890158 tipc: clean up so... |
2083 |
|
8ea642ee9 tipc: create TIPC... |
2084 |
if (tsk->probe_unacked) { |
b3be5e3e7 tipc: disconnect ... |
2085 |
if (!sock_owned_by_user(sk)) { |
9fd4b070f tipc: create TIPC... |
2086 |
tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
b3be5e3e7 tipc: disconnect ... |
2087 2088 2089 2090 2091 2092 2093 |
tipc_node_remove_conn(sock_net(sk), tsk_peer_node(tsk), tsk_peer_port(tsk)); sk->sk_state_change(sk); } else { /* Try again later */ sk_reset_timer(sk, &sk->sk_timer, (HZ / 20)); } |
360aab6b4 tipc: remove prob... |
2094 2095 |
bh_unlock_sock(sk); goto exit; |
572890158 tipc: clean up so... |
2096 |
} |
360aab6b4 tipc: remove prob... |
2097 2098 2099 2100 |
skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, 0, peer_node, own_node, peer_port, tsk->portid, TIPC_OK); |
8ea642ee9 tipc: create TIPC... |
2101 |
tsk->probe_unacked = true; |
360aab6b4 tipc: remove prob... |
2102 |
sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTERVAL); |
572890158 tipc: clean up so... |
2103 |
bh_unlock_sock(sk); |
a6ca10944 tipc: use generic... |
2104 |
if (skb) |
af9b028e2 tipc: make media ... |
2105 |
tipc_node_xmit_skb(sock_net(sk), skb, peer_node, tsk->portid); |
6c9808ce0 tipc: remove port... |
2106 |
exit: |
07f6c4bc0 tipc: convert tip... |
2107 |
sock_put(sk); |
572890158 tipc: clean up so... |
2108 |
} |
301bae56f tipc: merge struc... |
2109 |
static int tipc_sk_publish(struct tipc_sock *tsk, uint scope, |
0fc87aaeb tipc: remove sour... |
2110 2111 |
struct tipc_name_seq const *seq) { |
d6fb7e9c9 tipc: remove tsk-... |
2112 2113 |
struct sock *sk = &tsk->sk; struct net *net = sock_net(sk); |
0fc87aaeb tipc: remove sour... |
2114 2115 |
struct publication *publ; u32 key; |
d6fb7e9c9 tipc: remove tsk-... |
2116 |
if (tipc_sk_connected(sk)) |
0fc87aaeb tipc: remove sour... |
2117 |
return -EINVAL; |
07f6c4bc0 tipc: convert tip... |
2118 2119 |
key = tsk->portid + tsk->pub_count + 1; if (key == tsk->portid) |
0fc87aaeb tipc: remove sour... |
2120 |
return -EADDRINUSE; |
f2f9800d4 tipc: make tipc n... |
2121 |
publ = tipc_nametbl_publish(net, seq->type, seq->lower, seq->upper, |
07f6c4bc0 tipc: convert tip... |
2122 |
scope, tsk->portid, key); |
0fc87aaeb tipc: remove sour... |
2123 2124 |
if (unlikely(!publ)) return -EINVAL; |
301bae56f tipc: merge struc... |
2125 2126 2127 |
list_add(&publ->pport_list, &tsk->publications); tsk->pub_count++; tsk->published = 1; |
0fc87aaeb tipc: remove sour... |
2128 2129 |
return 0; } |
301bae56f tipc: merge struc... |
2130 |
static int tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, |
0fc87aaeb tipc: remove sour... |
2131 2132 |
struct tipc_name_seq const *seq) { |
f2f9800d4 tipc: make tipc n... |
2133 |
struct net *net = sock_net(&tsk->sk); |
0fc87aaeb tipc: remove sour... |
2134 2135 2136 |
struct publication *publ; struct publication *safe; int rc = -EINVAL; |
301bae56f tipc: merge struc... |
2137 |
list_for_each_entry_safe(publ, safe, &tsk->publications, pport_list) { |
0fc87aaeb tipc: remove sour... |
2138 2139 2140 2141 2142 2143 2144 2145 2146 |
if (seq) { if (publ->scope != scope) continue; if (publ->type != seq->type) continue; if (publ->lower != seq->lower) continue; if (publ->upper != seq->upper) break; |
f2f9800d4 tipc: make tipc n... |
2147 |
tipc_nametbl_withdraw(net, publ->type, publ->lower, |
0fc87aaeb tipc: remove sour... |
2148 2149 2150 2151 |
publ->ref, publ->key); rc = 0; break; } |
f2f9800d4 tipc: make tipc n... |
2152 |
tipc_nametbl_withdraw(net, publ->type, publ->lower, |
0fc87aaeb tipc: remove sour... |
2153 2154 2155 |
publ->ref, publ->key); rc = 0; } |
301bae56f tipc: merge struc... |
2156 2157 |
if (list_empty(&tsk->publications)) tsk->published = 0; |
0fc87aaeb tipc: remove sour... |
2158 2159 |
return rc; } |
5a9ee0be3 tipc: use registr... |
2160 2161 2162 |
/* tipc_sk_reinit: set non-zero address in all existing sockets * when we go from standalone to network mode. */ |
e05b31f4b tipc: make tipc s... |
2163 |
void tipc_sk_reinit(struct net *net) |
5a9ee0be3 tipc: use registr... |
2164 |
{ |
e05b31f4b tipc: make tipc s... |
2165 |
struct tipc_net *tn = net_generic(net, tipc_net_id); |
40f9f4397 tipc: Fix tipc_sk... |
2166 |
struct rhashtable_iter iter; |
07f6c4bc0 tipc: convert tip... |
2167 |
struct tipc_sock *tsk; |
5a9ee0be3 tipc: use registr... |
2168 |
struct tipc_msg *msg; |
5a9ee0be3 tipc: use registr... |
2169 |
|
40f9f4397 tipc: Fix tipc_sk... |
2170 2171 2172 2173 |
rhashtable_walk_enter(&tn->sk_rht, &iter); do { tsk = ERR_PTR(rhashtable_walk_start(&iter)); |
6c7e983b2 tipc: Fix tipc_sk... |
2174 2175 |
if (IS_ERR(tsk)) goto walk_stop; |
40f9f4397 tipc: Fix tipc_sk... |
2176 2177 |
while ((tsk = rhashtable_walk_next(&iter)) && !IS_ERR(tsk)) { |
07f6c4bc0 tipc: convert tip... |
2178 2179 |
spin_lock_bh(&tsk->sk.sk_lock.slock); msg = &tsk->phdr; |
347475395 tipc: make tipc n... |
2180 2181 |
msg_set_prevnode(msg, tn->own_addr); msg_set_orignode(msg, tn->own_addr); |
07f6c4bc0 tipc: convert tip... |
2182 2183 |
spin_unlock_bh(&tsk->sk.sk_lock.slock); } |
6c7e983b2 tipc: Fix tipc_sk... |
2184 |
walk_stop: |
40f9f4397 tipc: Fix tipc_sk... |
2185 2186 |
rhashtable_walk_stop(&iter); } while (tsk == ERR_PTR(-EAGAIN)); |
8fed734df tipc: fix a missi... |
2187 2188 |
rhashtable_walk_exit(&iter); |
5a9ee0be3 tipc: use registr... |
2189 |
} |
e05b31f4b tipc: make tipc s... |
2190 |
static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid) |
808d90f9c tipc: remove file... |
2191 |
{ |
e05b31f4b tipc: make tipc s... |
2192 |
struct tipc_net *tn = net_generic(net, tipc_net_id); |
07f6c4bc0 tipc: convert tip... |
2193 |
struct tipc_sock *tsk; |
808d90f9c tipc: remove file... |
2194 |
|
07f6c4bc0 tipc: convert tip... |
2195 |
rcu_read_lock(); |
6cca7289d tipc: Use inlined... |
2196 |
tsk = rhashtable_lookup_fast(&tn->sk_rht, &portid, tsk_rht_params); |
07f6c4bc0 tipc: convert tip... |
2197 2198 2199 |
if (tsk) sock_hold(&tsk->sk); rcu_read_unlock(); |
808d90f9c tipc: remove file... |
2200 |
|
07f6c4bc0 tipc: convert tip... |
2201 |
return tsk; |
808d90f9c tipc: remove file... |
2202 |
} |
07f6c4bc0 tipc: convert tip... |
2203 |
static int tipc_sk_insert(struct tipc_sock *tsk) |
808d90f9c tipc: remove file... |
2204 |
{ |
e05b31f4b tipc: make tipc s... |
2205 2206 2207 |
struct sock *sk = &tsk->sk; struct net *net = sock_net(sk); struct tipc_net *tn = net_generic(net, tipc_net_id); |
07f6c4bc0 tipc: convert tip... |
2208 2209 |
u32 remaining = (TIPC_MAX_PORT - TIPC_MIN_PORT) + 1; u32 portid = prandom_u32() % remaining + TIPC_MIN_PORT; |
808d90f9c tipc: remove file... |
2210 |
|
07f6c4bc0 tipc: convert tip... |
2211 2212 2213 2214 2215 2216 |
while (remaining--) { portid++; if ((portid < TIPC_MIN_PORT) || (portid > TIPC_MAX_PORT)) portid = TIPC_MIN_PORT; tsk->portid = portid; sock_hold(&tsk->sk); |
6cca7289d tipc: Use inlined... |
2217 2218 |
if (!rhashtable_lookup_insert_fast(&tn->sk_rht, &tsk->node, tsk_rht_params)) |
07f6c4bc0 tipc: convert tip... |
2219 2220 |
return 0; sock_put(&tsk->sk); |
808d90f9c tipc: remove file... |
2221 |
} |
07f6c4bc0 tipc: convert tip... |
2222 |
return -1; |
808d90f9c tipc: remove file... |
2223 |
} |
07f6c4bc0 tipc: convert tip... |
2224 |
static void tipc_sk_remove(struct tipc_sock *tsk) |
808d90f9c tipc: remove file... |
2225 |
{ |
07f6c4bc0 tipc: convert tip... |
2226 |
struct sock *sk = &tsk->sk; |
e05b31f4b tipc: make tipc s... |
2227 |
struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id); |
808d90f9c tipc: remove file... |
2228 |
|
6cca7289d tipc: Use inlined... |
2229 |
if (!rhashtable_remove_fast(&tn->sk_rht, &tsk->node, tsk_rht_params)) { |
41c6d650f net: convert sock... |
2230 |
WARN_ON(refcount_read(&sk->sk_refcnt) == 1); |
07f6c4bc0 tipc: convert tip... |
2231 |
__sock_put(sk); |
808d90f9c tipc: remove file... |
2232 |
} |
808d90f9c tipc: remove file... |
2233 |
} |
6cca7289d tipc: Use inlined... |
2234 2235 2236 2237 2238 |
static const struct rhashtable_params tsk_rht_params = { .nelem_hint = 192, .head_offset = offsetof(struct tipc_sock, node), .key_offset = offsetof(struct tipc_sock, portid), .key_len = sizeof(u32), /* portid */ |
6cca7289d tipc: Use inlined... |
2239 2240 |
.max_size = 1048576, .min_size = 256, |
b5e2c150a rhashtable: Disab... |
2241 |
.automatic_shrinking = true, |
6cca7289d tipc: Use inlined... |
2242 |
}; |
e05b31f4b tipc: make tipc s... |
2243 |
int tipc_sk_rht_init(struct net *net) |
808d90f9c tipc: remove file... |
2244 |
{ |
e05b31f4b tipc: make tipc s... |
2245 |
struct tipc_net *tn = net_generic(net, tipc_net_id); |
6cca7289d tipc: Use inlined... |
2246 2247 |
return rhashtable_init(&tn->sk_rht, &tsk_rht_params); |
808d90f9c tipc: remove file... |
2248 |
} |
e05b31f4b tipc: make tipc s... |
2249 |
void tipc_sk_rht_destroy(struct net *net) |
808d90f9c tipc: remove file... |
2250 |
{ |
e05b31f4b tipc: make tipc s... |
2251 |
struct tipc_net *tn = net_generic(net, tipc_net_id); |
07f6c4bc0 tipc: convert tip... |
2252 2253 |
/* Wait for socket readers to complete */ synchronize_net(); |
808d90f9c tipc: remove file... |
2254 |
|
e05b31f4b tipc: make tipc s... |
2255 |
rhashtable_destroy(&tn->sk_rht); |
808d90f9c tipc: remove file... |
2256 2257 2258 |
} /** |
247f0f3c3 tipc: align tipc ... |
2259 |
* tipc_setsockopt - set socket option |
b97bf3fd8 [TIPC] Initial merge |
2260 2261 2262 2263 2264 |
* @sock: socket structure * @lvl: option level * @opt: option identifier * @ov: pointer to new option value * @ol: length of option value |
c43072852 [NET] TIPC: Fix w... |
2265 2266 |
* * For stream sockets only, accepts and ignores all IPPROTO_TCP options |
b97bf3fd8 [TIPC] Initial merge |
2267 |
* (to ease compatibility). |
c43072852 [NET] TIPC: Fix w... |
2268 |
* |
b97bf3fd8 [TIPC] Initial merge |
2269 2270 |
* Returns 0 on success, errno otherwise */ |
247f0f3c3 tipc: align tipc ... |
2271 2272 |
static int tipc_setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, unsigned int ol) |
b97bf3fd8 [TIPC] Initial merge |
2273 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
2274 |
struct sock *sk = sock->sk; |
58ed94424 tipc: align usage... |
2275 |
struct tipc_sock *tsk = tipc_sk(sk); |
01fd12bb1 tipc: make replic... |
2276 |
u32 value = 0; |
a08ef4768 tipc: uninitializ... |
2277 |
int res = 0; |
b97bf3fd8 [TIPC] Initial merge |
2278 |
|
c43072852 [NET] TIPC: Fix w... |
2279 2280 |
if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) return 0; |
b97bf3fd8 [TIPC] Initial merge |
2281 2282 |
if (lvl != SOL_TIPC) return -ENOPROTOOPT; |
01fd12bb1 tipc: make replic... |
2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 |
switch (opt) { case TIPC_IMPORTANCE: case TIPC_SRC_DROPPABLE: case TIPC_DEST_DROPPABLE: case TIPC_CONN_TIMEOUT: if (ol < sizeof(value)) return -EINVAL; res = get_user(value, (u32 __user *)ov); if (res) return res; break; default: if (ov || ol) return -EINVAL; } |
b97bf3fd8 [TIPC] Initial merge |
2299 |
|
0c3141e91 [TIPC]: Overhaul ... |
2300 |
lock_sock(sk); |
c43072852 [NET] TIPC: Fix w... |
2301 |
|
b97bf3fd8 [TIPC] Initial merge |
2302 2303 |
switch (opt) { case TIPC_IMPORTANCE: |
301bae56f tipc: merge struc... |
2304 |
res = tsk_set_importance(tsk, value); |
b97bf3fd8 [TIPC] Initial merge |
2305 2306 2307 |
break; case TIPC_SRC_DROPPABLE: if (sock->type != SOCK_STREAM) |
301bae56f tipc: merge struc... |
2308 |
tsk_set_unreliable(tsk, value); |
c43072852 [NET] TIPC: Fix w... |
2309 |
else |
b97bf3fd8 [TIPC] Initial merge |
2310 2311 2312 |
res = -ENOPROTOOPT; break; case TIPC_DEST_DROPPABLE: |
301bae56f tipc: merge struc... |
2313 |
tsk_set_unreturnable(tsk, value); |
b97bf3fd8 [TIPC] Initial merge |
2314 2315 |
break; case TIPC_CONN_TIMEOUT: |
a0f40f02e tipc: Prevent rou... |
2316 |
tipc_sk(sk)->conn_timeout = value; |
b97bf3fd8 [TIPC] Initial merge |
2317 |
break; |
01fd12bb1 tipc: make replic... |
2318 2319 2320 2321 2322 2323 2324 2325 |
case TIPC_MCAST_BROADCAST: tsk->mc_method.rcast = false; tsk->mc_method.mandatory = true; break; case TIPC_MCAST_REPLICAST: tsk->mc_method.rcast = true; tsk->mc_method.mandatory = true; break; |
b97bf3fd8 [TIPC] Initial merge |
2326 2327 2328 |
default: res = -EINVAL; } |
0c3141e91 [TIPC]: Overhaul ... |
2329 |
release_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
2330 2331 2332 2333 |
return res; } /** |
247f0f3c3 tipc: align tipc ... |
2334 |
* tipc_getsockopt - get socket option |
b97bf3fd8 [TIPC] Initial merge |
2335 2336 2337 2338 2339 |
* @sock: socket structure * @lvl: option level * @opt: option identifier * @ov: receptacle for option value * @ol: receptacle for length of option value |
c43072852 [NET] TIPC: Fix w... |
2340 2341 |
* * For stream sockets only, returns 0 length result for all IPPROTO_TCP options |
b97bf3fd8 [TIPC] Initial merge |
2342 |
* (to ease compatibility). |
c43072852 [NET] TIPC: Fix w... |
2343 |
* |
b97bf3fd8 [TIPC] Initial merge |
2344 2345 |
* Returns 0 on success, errno otherwise */ |
247f0f3c3 tipc: align tipc ... |
2346 2347 |
static int tipc_getsockopt(struct socket *sock, int lvl, int opt, char __user *ov, int __user *ol) |
b97bf3fd8 [TIPC] Initial merge |
2348 |
{ |
0c3141e91 [TIPC]: Overhaul ... |
2349 |
struct sock *sk = sock->sk; |
58ed94424 tipc: align usage... |
2350 |
struct tipc_sock *tsk = tipc_sk(sk); |
c43072852 [NET] TIPC: Fix w... |
2351 |
int len; |
b97bf3fd8 [TIPC] Initial merge |
2352 |
u32 value; |
c43072852 [NET] TIPC: Fix w... |
2353 |
int res; |
b97bf3fd8 [TIPC] Initial merge |
2354 |
|
c43072852 [NET] TIPC: Fix w... |
2355 2356 |
if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) return put_user(0, ol); |
b97bf3fd8 [TIPC] Initial merge |
2357 2358 |
if (lvl != SOL_TIPC) return -ENOPROTOOPT; |
2db9983a4 tipc: split varia... |
2359 2360 |
res = get_user(len, ol); if (res) |
c43072852 [NET] TIPC: Fix w... |
2361 |
return res; |
b97bf3fd8 [TIPC] Initial merge |
2362 |
|
0c3141e91 [TIPC]: Overhaul ... |
2363 |
lock_sock(sk); |
b97bf3fd8 [TIPC] Initial merge |
2364 2365 2366 |
switch (opt) { case TIPC_IMPORTANCE: |
301bae56f tipc: merge struc... |
2367 |
value = tsk_importance(tsk); |
b97bf3fd8 [TIPC] Initial merge |
2368 2369 |
break; case TIPC_SRC_DROPPABLE: |
301bae56f tipc: merge struc... |
2370 |
value = tsk_unreliable(tsk); |
b97bf3fd8 [TIPC] Initial merge |
2371 2372 |
break; case TIPC_DEST_DROPPABLE: |
301bae56f tipc: merge struc... |
2373 |
value = tsk_unreturnable(tsk); |
b97bf3fd8 [TIPC] Initial merge |
2374 2375 |
break; case TIPC_CONN_TIMEOUT: |
301bae56f tipc: merge struc... |
2376 |
value = tsk->conn_timeout; |
0c3141e91 [TIPC]: Overhaul ... |
2377 |
/* no need to set "res", since already 0 at this point */ |
b97bf3fd8 [TIPC] Initial merge |
2378 |
break; |
0e65967e3 tipc: cleanup var... |
2379 |
case TIPC_NODE_RECVQ_DEPTH: |
9da3d4758 tipc: eliminate a... |
2380 |
value = 0; /* was tipc_queue_size, now obsolete */ |
6650613d3 tipc: Add socket ... |
2381 |
break; |
0e65967e3 tipc: cleanup var... |
2382 |
case TIPC_SOCK_RECVQ_DEPTH: |
6650613d3 tipc: Add socket ... |
2383 2384 |
value = skb_queue_len(&sk->sk_receive_queue); break; |
b97bf3fd8 [TIPC] Initial merge |
2385 2386 2387 |
default: res = -EINVAL; } |
0c3141e91 [TIPC]: Overhaul ... |
2388 |
release_sock(sk); |
25860c3bd tipc: recode gets... |
2389 2390 |
if (res) return res; /* "get" failed */ |
b97bf3fd8 [TIPC] Initial merge |
2391 |
|
25860c3bd tipc: recode gets... |
2392 2393 2394 2395 2396 2397 2398 |
if (len < sizeof(value)) return -EINVAL; if (copy_to_user(ov, &value, sizeof(value))) return -EFAULT; return put_user(sizeof(value), ol); |
b97bf3fd8 [TIPC] Initial merge |
2399 |
} |
f2f9800d4 tipc: make tipc n... |
2400 |
static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
78acb1f9b tipc: add ioctl t... |
2401 |
{ |
f2f9800d4 tipc: make tipc n... |
2402 |
struct sock *sk = sock->sk; |
78acb1f9b tipc: add ioctl t... |
2403 2404 2405 2406 2407 2408 2409 |
struct tipc_sioc_ln_req lnr; void __user *argp = (void __user *)arg; switch (cmd) { case SIOCGETLINKNAME: if (copy_from_user(&lnr, argp, sizeof(lnr))) return -EFAULT; |
f2f9800d4 tipc: make tipc n... |
2410 2411 |
if (!tipc_node_get_linkname(sock_net(sk), lnr.bearer_id & 0xffff, lnr.peer, |
78acb1f9b tipc: add ioctl t... |
2412 2413 2414 2415 2416 2417 |
lnr.linkname, TIPC_MAX_LINK_NAME)) { if (copy_to_user(argp, &lnr, sizeof(lnr))) return -EFAULT; return 0; } return -EADDRNOTAVAIL; |
78acb1f9b tipc: add ioctl t... |
2418 2419 2420 2421 |
default: return -ENOIOCTLCMD; } } |
70b03759e tipc: add support... |
2422 2423 2424 2425 |
static int tipc_socketpair(struct socket *sock1, struct socket *sock2) { struct tipc_sock *tsk2 = tipc_sk(sock2->sk); struct tipc_sock *tsk1 = tipc_sk(sock1->sk); |
66bc1e8d5 tipc: allow rdm/d... |
2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 |
u32 onode = tipc_own_addr(sock_net(sock1->sk)); tsk1->peer.family = AF_TIPC; tsk1->peer.addrtype = TIPC_ADDR_ID; tsk1->peer.scope = TIPC_NODE_SCOPE; tsk1->peer.addr.id.ref = tsk2->portid; tsk1->peer.addr.id.node = onode; tsk2->peer.family = AF_TIPC; tsk2->peer.addrtype = TIPC_ADDR_ID; tsk2->peer.scope = TIPC_NODE_SCOPE; tsk2->peer.addr.id.ref = tsk1->portid; tsk2->peer.addr.id.node = onode; tipc_sk_finish_conn(tsk1, tsk2->portid, onode); tipc_sk_finish_conn(tsk2, tsk1->portid, onode); |
70b03759e tipc: add support... |
2441 2442 |
return 0; } |
ae86b9e38 net: Fix non-kern... |
2443 |
/* Protocol switches for the various types of TIPC sockets */ |
bca65eae3 [TIPC]: declare p... |
2444 |
static const struct proto_ops msg_ops = { |
0e65967e3 tipc: cleanup var... |
2445 |
.owner = THIS_MODULE, |
b97bf3fd8 [TIPC] Initial merge |
2446 |
.family = AF_TIPC, |
247f0f3c3 tipc: align tipc ... |
2447 2448 2449 |
.release = tipc_release, .bind = tipc_bind, .connect = tipc_connect, |
66bc1e8d5 tipc: allow rdm/d... |
2450 |
.socketpair = tipc_socketpair, |
245f3d342 tipc: Simplify pr... |
2451 |
.accept = sock_no_accept, |
247f0f3c3 tipc: align tipc ... |
2452 2453 |
.getname = tipc_getname, .poll = tipc_poll, |
78acb1f9b tipc: add ioctl t... |
2454 |
.ioctl = tipc_ioctl, |
245f3d342 tipc: Simplify pr... |
2455 |
.listen = sock_no_listen, |
247f0f3c3 tipc: align tipc ... |
2456 2457 2458 2459 2460 |
.shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, .getsockopt = tipc_getsockopt, .sendmsg = tipc_sendmsg, .recvmsg = tipc_recvmsg, |
8238745a3 [NET] TIPC: Fix w... |
2461 2462 |
.mmap = sock_no_mmap, .sendpage = sock_no_sendpage |
b97bf3fd8 [TIPC] Initial merge |
2463 |
}; |
bca65eae3 [TIPC]: declare p... |
2464 |
static const struct proto_ops packet_ops = { |
0e65967e3 tipc: cleanup var... |
2465 |
.owner = THIS_MODULE, |
b97bf3fd8 [TIPC] Initial merge |
2466 |
.family = AF_TIPC, |
247f0f3c3 tipc: align tipc ... |
2467 2468 2469 |
.release = tipc_release, .bind = tipc_bind, .connect = tipc_connect, |
70b03759e tipc: add support... |
2470 |
.socketpair = tipc_socketpair, |
247f0f3c3 tipc: align tipc ... |
2471 2472 2473 |
.accept = tipc_accept, .getname = tipc_getname, .poll = tipc_poll, |
78acb1f9b tipc: add ioctl t... |
2474 |
.ioctl = tipc_ioctl, |
247f0f3c3 tipc: align tipc ... |
2475 2476 2477 2478 2479 2480 |
.listen = tipc_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, .getsockopt = tipc_getsockopt, .sendmsg = tipc_send_packet, .recvmsg = tipc_recvmsg, |
8238745a3 [NET] TIPC: Fix w... |
2481 2482 |
.mmap = sock_no_mmap, .sendpage = sock_no_sendpage |
b97bf3fd8 [TIPC] Initial merge |
2483 |
}; |
bca65eae3 [TIPC]: declare p... |
2484 |
static const struct proto_ops stream_ops = { |
0e65967e3 tipc: cleanup var... |
2485 |
.owner = THIS_MODULE, |
b97bf3fd8 [TIPC] Initial merge |
2486 |
.family = AF_TIPC, |
247f0f3c3 tipc: align tipc ... |
2487 2488 2489 |
.release = tipc_release, .bind = tipc_bind, .connect = tipc_connect, |
70b03759e tipc: add support... |
2490 |
.socketpair = tipc_socketpair, |
247f0f3c3 tipc: align tipc ... |
2491 2492 2493 |
.accept = tipc_accept, .getname = tipc_getname, .poll = tipc_poll, |
78acb1f9b tipc: add ioctl t... |
2494 |
.ioctl = tipc_ioctl, |
247f0f3c3 tipc: align tipc ... |
2495 2496 2497 2498 |
.listen = tipc_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, .getsockopt = tipc_getsockopt, |
365ad353c tipc: reduce risk... |
2499 |
.sendmsg = tipc_sendstream, |
ec8a09fbb tipc: refactor fu... |
2500 |
.recvmsg = tipc_recvstream, |
8238745a3 [NET] TIPC: Fix w... |
2501 2502 |
.mmap = sock_no_mmap, .sendpage = sock_no_sendpage |
b97bf3fd8 [TIPC] Initial merge |
2503 |
}; |
bca65eae3 [TIPC]: declare p... |
2504 |
static const struct net_proto_family tipc_family_ops = { |
0e65967e3 tipc: cleanup var... |
2505 |
.owner = THIS_MODULE, |
b97bf3fd8 [TIPC] Initial merge |
2506 |
.family = AF_TIPC, |
c5fa7b3cf tipc: introduce n... |
2507 |
.create = tipc_sk_create |
b97bf3fd8 [TIPC] Initial merge |
2508 2509 2510 2511 2512 |
}; static struct proto tipc_proto = { .name = "TIPC", .owner = THIS_MODULE, |
cc79dd1ba tipc: change sock... |
2513 2514 |
.obj_size = sizeof(struct tipc_sock), .sysctl_rmem = sysctl_tipc_rmem |
b97bf3fd8 [TIPC] Initial merge |
2515 2516 2517 |
}; /** |
4323add67 [TIPC] Avoid poll... |
2518 |
* tipc_socket_init - initialize TIPC socket interface |
c43072852 [NET] TIPC: Fix w... |
2519 |
* |
b97bf3fd8 [TIPC] Initial merge |
2520 2521 |
* Returns 0 on success, errno otherwise */ |
4323add67 [TIPC] Avoid poll... |
2522 |
int tipc_socket_init(void) |
b97bf3fd8 [TIPC] Initial merge |
2523 2524 |
{ int res; |
c43072852 [NET] TIPC: Fix w... |
2525 |
res = proto_register(&tipc_proto, 1); |
b97bf3fd8 [TIPC] Initial merge |
2526 |
if (res) { |
2cf8aa19f tipc: use standar... |
2527 2528 |
pr_err("Failed to register TIPC protocol type "); |
b97bf3fd8 [TIPC] Initial merge |
2529 2530 2531 2532 2533 |
goto out; } res = sock_register(&tipc_family_ops); if (res) { |
2cf8aa19f tipc: use standar... |
2534 2535 |
pr_err("Failed to register TIPC socket type "); |
b97bf3fd8 [TIPC] Initial merge |
2536 2537 2538 |
proto_unregister(&tipc_proto); goto out; } |
b97bf3fd8 [TIPC] Initial merge |
2539 2540 2541 2542 2543 |
out: return res; } /** |
4323add67 [TIPC] Avoid poll... |
2544 |
* tipc_socket_stop - stop TIPC socket interface |
b97bf3fd8 [TIPC] Initial merge |
2545 |
*/ |
4323add67 [TIPC] Avoid poll... |
2546 |
void tipc_socket_stop(void) |
b97bf3fd8 [TIPC] Initial merge |
2547 |
{ |
b97bf3fd8 [TIPC] Initial merge |
2548 2549 2550 |
sock_unregister(tipc_family_ops.family); proto_unregister(&tipc_proto); } |
34b78a127 tipc: add sock du... |
2551 2552 |
/* Caller should hold socket lock for the passed tipc socket. */ |
d8182804c tipc: fix sparse ... |
2553 |
static int __tipc_nl_add_sk_con(struct sk_buff *skb, struct tipc_sock *tsk) |
34b78a127 tipc: add sock du... |
2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 |
{ u32 peer_node; u32 peer_port; struct nlattr *nest; peer_node = tsk_peer_node(tsk); peer_port = tsk_peer_port(tsk); nest = nla_nest_start(skb, TIPC_NLA_SOCK_CON); if (nla_put_u32(skb, TIPC_NLA_CON_NODE, peer_node)) goto msg_full; if (nla_put_u32(skb, TIPC_NLA_CON_SOCK, peer_port)) goto msg_full; if (tsk->conn_type != 0) { if (nla_put_flag(skb, TIPC_NLA_CON_FLAG)) goto msg_full; if (nla_put_u32(skb, TIPC_NLA_CON_TYPE, tsk->conn_type)) goto msg_full; if (nla_put_u32(skb, TIPC_NLA_CON_INST, tsk->conn_instance)) goto msg_full; } nla_nest_end(skb, nest); return 0; msg_full: nla_nest_cancel(skb, nest); return -EMSGSIZE; } /* Caller should hold socket lock for the passed tipc socket. */ |
d8182804c tipc: fix sparse ... |
2588 2589 |
static int __tipc_nl_add_sk(struct sk_buff *skb, struct netlink_callback *cb, struct tipc_sock *tsk) |
34b78a127 tipc: add sock du... |
2590 2591 2592 2593 |
{ int err; void *hdr; struct nlattr *attrs; |
347475395 tipc: make tipc n... |
2594 2595 |
struct net *net = sock_net(skb->sk); struct tipc_net *tn = net_generic(net, tipc_net_id); |
d6fb7e9c9 tipc: remove tsk-... |
2596 |
struct sock *sk = &tsk->sk; |
34b78a127 tipc: add sock du... |
2597 2598 |
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, |
bfb3e5dd8 tipc: move and re... |
2599 |
&tipc_genl_family, NLM_F_MULTI, TIPC_NL_SOCK_GET); |
34b78a127 tipc: add sock du... |
2600 2601 2602 2603 2604 2605 |
if (!hdr) goto msg_cancel; attrs = nla_nest_start(skb, TIPC_NLA_SOCK); if (!attrs) goto genlmsg_cancel; |
07f6c4bc0 tipc: convert tip... |
2606 |
if (nla_put_u32(skb, TIPC_NLA_SOCK_REF, tsk->portid)) |
34b78a127 tipc: add sock du... |
2607 |
goto attr_msg_cancel; |
347475395 tipc: make tipc n... |
2608 |
if (nla_put_u32(skb, TIPC_NLA_SOCK_ADDR, tn->own_addr)) |
34b78a127 tipc: add sock du... |
2609 |
goto attr_msg_cancel; |
d6fb7e9c9 tipc: remove tsk-... |
2610 |
if (tipc_sk_connected(sk)) { |
34b78a127 tipc: add sock du... |
2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 |
err = __tipc_nl_add_sk_con(skb, tsk); if (err) goto attr_msg_cancel; } else if (!list_empty(&tsk->publications)) { if (nla_put_flag(skb, TIPC_NLA_SOCK_HAS_PUBL)) goto attr_msg_cancel; } nla_nest_end(skb, attrs); genlmsg_end(skb, hdr); return 0; attr_msg_cancel: nla_nest_cancel(skb, attrs); genlmsg_cancel: genlmsg_cancel(skb, hdr); msg_cancel: return -EMSGSIZE; } int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb) { int err; struct tipc_sock *tsk; |
07f6c4bc0 tipc: convert tip... |
2635 2636 |
const struct bucket_table *tbl; struct rhash_head *pos; |
e05b31f4b tipc: make tipc s... |
2637 2638 |
struct net *net = sock_net(skb->sk); struct tipc_net *tn = net_generic(net, tipc_net_id); |
d6e164e32 tipc: fix socket ... |
2639 2640 |
u32 tbl_id = cb->args[0]; u32 prev_portid = cb->args[1]; |
34b78a127 tipc: add sock du... |
2641 |
|
07f6c4bc0 tipc: convert tip... |
2642 |
rcu_read_lock(); |
e05b31f4b tipc: make tipc s... |
2643 |
tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); |
d6e164e32 tipc: fix socket ... |
2644 2645 |
for (; tbl_id < tbl->size; tbl_id++) { rht_for_each_entry_rcu(tsk, pos, tbl, tbl_id, node) { |
07f6c4bc0 tipc: convert tip... |
2646 |
spin_lock_bh(&tsk->sk.sk_lock.slock); |
d6e164e32 tipc: fix socket ... |
2647 2648 2649 2650 |
if (prev_portid && prev_portid != tsk->portid) { spin_unlock_bh(&tsk->sk.sk_lock.slock); continue; } |
07f6c4bc0 tipc: convert tip... |
2651 |
err = __tipc_nl_add_sk(skb, cb, tsk); |
d6e164e32 tipc: fix socket ... |
2652 2653 2654 2655 2656 2657 |
if (err) { prev_portid = tsk->portid; spin_unlock_bh(&tsk->sk.sk_lock.slock); goto out; } prev_portid = 0; |
07f6c4bc0 tipc: convert tip... |
2658 |
spin_unlock_bh(&tsk->sk.sk_lock.slock); |
07f6c4bc0 tipc: convert tip... |
2659 |
} |
34b78a127 tipc: add sock du... |
2660 |
} |
d6e164e32 tipc: fix socket ... |
2661 |
out: |
07f6c4bc0 tipc: convert tip... |
2662 |
rcu_read_unlock(); |
d6e164e32 tipc: fix socket ... |
2663 2664 |
cb->args[0] = tbl_id; cb->args[1] = prev_portid; |
34b78a127 tipc: add sock du... |
2665 2666 2667 |
return skb->len; } |
1a1a143da tipc: add publica... |
2668 2669 |
/* Caller should hold socket lock for the passed tipc socket. */ |
d8182804c tipc: fix sparse ... |
2670 2671 2672 |
static int __tipc_nl_add_sk_publ(struct sk_buff *skb, struct netlink_callback *cb, struct publication *publ) |
1a1a143da tipc: add publica... |
2673 2674 2675 2676 2677 |
{ void *hdr; struct nlattr *attrs; hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, |
bfb3e5dd8 tipc: move and re... |
2678 |
&tipc_genl_family, NLM_F_MULTI, TIPC_NL_PUBL_GET); |
1a1a143da tipc: add publica... |
2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 |
if (!hdr) goto msg_cancel; attrs = nla_nest_start(skb, TIPC_NLA_PUBL); if (!attrs) goto genlmsg_cancel; if (nla_put_u32(skb, TIPC_NLA_PUBL_KEY, publ->key)) goto attr_msg_cancel; if (nla_put_u32(skb, TIPC_NLA_PUBL_TYPE, publ->type)) goto attr_msg_cancel; if (nla_put_u32(skb, TIPC_NLA_PUBL_LOWER, publ->lower)) goto attr_msg_cancel; if (nla_put_u32(skb, TIPC_NLA_PUBL_UPPER, publ->upper)) goto attr_msg_cancel; nla_nest_end(skb, attrs); genlmsg_end(skb, hdr); return 0; attr_msg_cancel: nla_nest_cancel(skb, attrs); genlmsg_cancel: genlmsg_cancel(skb, hdr); msg_cancel: return -EMSGSIZE; } /* Caller should hold socket lock for the passed tipc socket. */ |
d8182804c tipc: fix sparse ... |
2709 2710 2711 |
static int __tipc_nl_list_sk_publ(struct sk_buff *skb, struct netlink_callback *cb, struct tipc_sock *tsk, u32 *last_publ) |
1a1a143da tipc: add publica... |
2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 |
{ int err; struct publication *p; if (*last_publ) { list_for_each_entry(p, &tsk->publications, pport_list) { if (p->key == *last_publ) break; } if (p->key != *last_publ) { /* We never set seq or call nl_dump_check_consistent() * this means that setting prev_seq here will cause the * consistence check to fail in the netlink callback * handler. Resulting in the last NLMSG_DONE message * having the NLM_F_DUMP_INTR flag set. */ cb->prev_seq = 1; *last_publ = 0; return -EPIPE; } } else { p = list_first_entry(&tsk->publications, struct publication, pport_list); } list_for_each_entry_from(p, &tsk->publications, pport_list) { err = __tipc_nl_add_sk_publ(skb, cb, p); if (err) { *last_publ = p->key; return err; } } *last_publ = 0; return 0; } int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb) { int err; |
07f6c4bc0 tipc: convert tip... |
2752 |
u32 tsk_portid = cb->args[0]; |
1a1a143da tipc: add publica... |
2753 2754 |
u32 last_publ = cb->args[1]; u32 done = cb->args[2]; |
e05b31f4b tipc: make tipc s... |
2755 |
struct net *net = sock_net(skb->sk); |
1a1a143da tipc: add publica... |
2756 |
struct tipc_sock *tsk; |
07f6c4bc0 tipc: convert tip... |
2757 |
if (!tsk_portid) { |
1a1a143da tipc: add publica... |
2758 2759 2760 2761 2762 2763 |
struct nlattr **attrs; struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1]; err = tipc_nlmsg_parse(cb->nlh, &attrs); if (err) return err; |
45e093ae2 tipc: check nl so... |
2764 2765 |
if (!attrs[TIPC_NLA_SOCK]) return -EINVAL; |
1a1a143da tipc: add publica... |
2766 2767 |
err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], |
fceb6435e netlink: pass ext... |
2768 |
tipc_nl_sock_policy, NULL); |
1a1a143da tipc: add publica... |
2769 2770 2771 2772 2773 |
if (err) return err; if (!sock[TIPC_NLA_SOCK_REF]) return -EINVAL; |
07f6c4bc0 tipc: convert tip... |
2774 |
tsk_portid = nla_get_u32(sock[TIPC_NLA_SOCK_REF]); |
1a1a143da tipc: add publica... |
2775 2776 2777 2778 |
} if (done) return 0; |
e05b31f4b tipc: make tipc s... |
2779 |
tsk = tipc_sk_lookup(net, tsk_portid); |
1a1a143da tipc: add publica... |
2780 2781 2782 2783 2784 2785 2786 2787 |
if (!tsk) return -EINVAL; lock_sock(&tsk->sk); err = __tipc_nl_list_sk_publ(skb, cb, tsk, &last_publ); if (!err) done = 1; release_sock(&tsk->sk); |
07f6c4bc0 tipc: convert tip... |
2788 |
sock_put(&tsk->sk); |
1a1a143da tipc: add publica... |
2789 |
|
07f6c4bc0 tipc: convert tip... |
2790 |
cb->args[0] = tsk_portid; |
1a1a143da tipc: add publica... |
2791 2792 2793 2794 2795 |
cb->args[1] = last_publ; cb->args[2] = done; return skb->len; } |