Blame view
net/caif/caif_socket.c
26.5 KB
af873fcec treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
e6f95ec8d net-caif: add CAI... |
2 3 |
/* * Copyright (C) ST-Ericsson AB 2010 |
26ee65e68 caif: Remove my b... |
4 |
* Author: Sjur Brendeland |
e6f95ec8d net-caif: add CAI... |
5 |
*/ |
b31fa5bad net/caif: Use pr_fmt |
6 |
#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ |
e6f95ec8d net-caif: add CAI... |
7 8 9 |
#include <linux/fs.h> #include <linux/init.h> #include <linux/module.h> |
3f07c0144 sched/headers: Pr... |
10 |
#include <linux/sched/signal.h> |
e6f95ec8d net-caif: add CAI... |
11 12 13 14 15 16 17 |
#include <linux/spinlock.h> #include <linux/mutex.h> #include <linux/list.h> #include <linux/wait.h> #include <linux/poll.h> #include <linux/tcp.h> #include <linux/uaccess.h> |
bece7b239 caif: Rewritten s... |
18 |
#include <linux/debugfs.h> |
e6f95ec8d net-caif: add CAI... |
19 |
#include <linux/caif/caif_socket.h> |
447648128 caif: set traffic... |
20 |
#include <linux/pkt_sched.h> |
bece7b239 caif: Rewritten s... |
21 22 |
#include <net/sock.h> #include <net/tcp_states.h> |
e6f95ec8d net-caif: add CAI... |
23 24 25 26 27 |
#include <net/caif/caif_layer.h> #include <net/caif/caif_dev.h> #include <net/caif/cfpkt.h> MODULE_LICENSE("GPL"); |
bece7b239 caif: Rewritten s... |
28 |
MODULE_ALIAS_NETPROTO(AF_CAIF); |
bece7b239 caif: Rewritten s... |
29 30 31 32 33 34 35 36 37 38 39 40 41 |
/* * CAIF state is re-using the TCP socket states. * caif_states stored in sk_state reflect the state as reported by * the CAIF stack, while sk_socket->state is the state of the socket. */ enum caif_states { CAIF_CONNECTED = TCP_ESTABLISHED, CAIF_CONNECTING = TCP_SYN_SENT, CAIF_DISCONNECTED = TCP_CLOSE }; #define TX_FLOW_ON_BIT 1 #define RX_FLOW_ON_BIT 2 |
e6f95ec8d net-caif: add CAI... |
42 |
|
e6f95ec8d net-caif: add CAI... |
43 |
struct caifsock { |
bece7b239 caif: Rewritten s... |
44 |
struct sock sk; /* must be first member */ |
e6f95ec8d net-caif: add CAI... |
45 |
struct cflayer layer; |
e6f95ec8d net-caif: add CAI... |
46 |
u32 flow_state; |
e6f95ec8d net-caif: add CAI... |
47 |
struct caif_connect_request conn_req; |
bece7b239 caif: Rewritten s... |
48 |
struct mutex readlock; |
e6f95ec8d net-caif: add CAI... |
49 |
struct dentry *debugfs_socket_dir; |
2aa40aef9 caif: Use link la... |
50 |
int headroom, tailroom, maxframe; |
e6f95ec8d net-caif: add CAI... |
51 |
}; |
bece7b239 caif: Rewritten s... |
52 53 54 55 56 57 58 59 60 61 62 |
static int rx_flow_is_on(struct caifsock *cf_sk) { return test_bit(RX_FLOW_ON_BIT, (void *) &cf_sk->flow_state); } static int tx_flow_is_on(struct caifsock *cf_sk) { return test_bit(TX_FLOW_ON_BIT, (void *) &cf_sk->flow_state); } |
e6f95ec8d net-caif: add CAI... |
63 |
|
bece7b239 caif: Rewritten s... |
64 |
static void set_rx_flow_off(struct caifsock *cf_sk) |
e6f95ec8d net-caif: add CAI... |
65 |
{ |
bece7b239 caif: Rewritten s... |
66 67 68 |
clear_bit(RX_FLOW_ON_BIT, (void *) &cf_sk->flow_state); } |
e6f95ec8d net-caif: add CAI... |
69 |
|
bece7b239 caif: Rewritten s... |
70 71 72 73 74 |
static void set_rx_flow_on(struct caifsock *cf_sk) { set_bit(RX_FLOW_ON_BIT, (void *) &cf_sk->flow_state); } |
e6f95ec8d net-caif: add CAI... |
75 |
|
bece7b239 caif: Rewritten s... |
76 77 78 79 80 |
static void set_tx_flow_off(struct caifsock *cf_sk) { clear_bit(TX_FLOW_ON_BIT, (void *) &cf_sk->flow_state); } |
e6f95ec8d net-caif: add CAI... |
81 |
|
bece7b239 caif: Rewritten s... |
82 83 84 85 86 |
static void set_tx_flow_on(struct caifsock *cf_sk) { set_bit(TX_FLOW_ON_BIT, (void *) &cf_sk->flow_state); } |
e6f95ec8d net-caif: add CAI... |
87 |
|
bece7b239 caif: Rewritten s... |
88 89 90 91 92 93 |
static void caif_read_lock(struct sock *sk) { struct caifsock *cf_sk; cf_sk = container_of(sk, struct caifsock, sk); mutex_lock(&cf_sk->readlock); } |
e6f95ec8d net-caif: add CAI... |
94 |
|
bece7b239 caif: Rewritten s... |
95 96 97 98 99 100 |
static void caif_read_unlock(struct sock *sk) { struct caifsock *cf_sk; cf_sk = container_of(sk, struct caifsock, sk); mutex_unlock(&cf_sk->readlock); } |
e6f95ec8d net-caif: add CAI... |
101 |
|
a9a8f1070 caif: Bugfix - mi... |
102 |
static int sk_rcvbuf_lowwater(struct caifsock *cf_sk) |
bece7b239 caif: Rewritten s... |
103 104 105 106 |
{ /* A quarter of full buffer is used a low water mark */ return cf_sk->sk.sk_rcvbuf / 4; } |
e6f95ec8d net-caif: add CAI... |
107 |
|
a9a8f1070 caif: Bugfix - mi... |
108 |
static void caif_flow_ctrl(struct sock *sk, int mode) |
bece7b239 caif: Rewritten s... |
109 110 111 |
{ struct caifsock *cf_sk; cf_sk = container_of(sk, struct caifsock, sk); |
ca6a09f25 caif: Bugfix - Po... |
112 |
if (cf_sk->layer.dn && cf_sk->layer.dn->modemcmd) |
bece7b239 caif: Rewritten s... |
113 114 |
cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode); } |
e6f95ec8d net-caif: add CAI... |
115 |
|
bece7b239 caif: Rewritten s... |
116 117 118 119 |
/* * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are * not dropped, but CAIF is sending flow off instead. */ |
b8a23e8d8 caif: fix leaks a... |
120 |
static void caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
bece7b239 caif: Rewritten s... |
121 122 |
{ int err; |
bece7b239 caif: Rewritten s... |
123 124 125 |
unsigned long flags; struct sk_buff_head *list = &sk->sk_receive_queue; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
b8a23e8d8 caif: fix leaks a... |
126 |
bool queued = false; |
e6f95ec8d net-caif: add CAI... |
127 |
|
bece7b239 caif: Rewritten s... |
128 |
if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
95c961747 net: cleanup unsi... |
129 |
(unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { |
e87cc4728 net: Convert net_... |
130 131 132 133 |
net_dbg_ratelimited("sending flow OFF (queue len = %d %d) ", atomic_read(&cf_sk->sk.sk_rmem_alloc), sk_rcvbuf_lowwater(cf_sk)); |
bece7b239 caif: Rewritten s... |
134 |
set_rx_flow_off(cf_sk); |
ca6a09f25 caif: Bugfix - Po... |
135 |
caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); |
bece7b239 caif: Rewritten s... |
136 |
} |
e6f95ec8d net-caif: add CAI... |
137 |
|
bece7b239 caif: Rewritten s... |
138 139 |
err = sk_filter(sk, skb); if (err) |
b8a23e8d8 caif: fix leaks a... |
140 |
goto out; |
c76562b67 netvm: prevent a ... |
141 |
if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { |
bece7b239 caif: Rewritten s... |
142 |
set_rx_flow_off(cf_sk); |
e87cc4728 net: Convert net_... |
143 144 |
net_dbg_ratelimited("sending flow OFF due to rmem_schedule "); |
ca6a09f25 caif: Bugfix - Po... |
145 |
caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); |
bece7b239 caif: Rewritten s... |
146 147 148 |
} skb->dev = NULL; skb_set_owner_r(skb, sk); |
bece7b239 caif: Rewritten s... |
149 |
spin_lock_irqsave(&list->lock, flags); |
b8a23e8d8 caif: fix leaks a... |
150 151 |
queued = !sock_flag(sk, SOCK_DEAD); if (queued) |
bece7b239 caif: Rewritten s... |
152 153 |
__skb_queue_tail(list, skb); spin_unlock_irqrestore(&list->lock, flags); |
b8a23e8d8 caif: fix leaks a... |
154 155 |
out: if (queued) |
676d23690 net: Fix use afte... |
156 |
sk->sk_data_ready(sk); |
bece7b239 caif: Rewritten s... |
157 158 |
else kfree_skb(skb); |
e6f95ec8d net-caif: add CAI... |
159 |
} |
bece7b239 caif: Rewritten s... |
160 161 |
/* Packet Receive Callback function called from CAIF Stack */ static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) |
e6f95ec8d net-caif: add CAI... |
162 163 |
{ struct caifsock *cf_sk; |
bece7b239 caif: Rewritten s... |
164 |
struct sk_buff *skb; |
e6f95ec8d net-caif: add CAI... |
165 166 |
cf_sk = container_of(layr, struct caifsock, layer); |
bece7b239 caif: Rewritten s... |
167 168 169 |
skb = cfpkt_tonative(pkt); if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { |
3f874adc4 caif: remove unes... |
170 |
kfree_skb(skb); |
bece7b239 caif: Rewritten s... |
171 172 173 174 175 |
return 0; } caif_queue_rcv_skb(&cf_sk->sk, skb); return 0; } |
e6f95ec8d net-caif: add CAI... |
176 |
|
b3ccfbe40 caif: Protected i... |
177 178 179 180 181 182 183 184 185 186 187 |
static void cfsk_hold(struct cflayer *layr) { struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); sock_hold(&cf_sk->sk); } static void cfsk_put(struct cflayer *layr) { struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); sock_put(&cf_sk->sk); } |
bece7b239 caif: Rewritten s... |
188 189 |
/* Packet Control Callback function called from CAIF */ static void caif_ctrl_cb(struct cflayer *layr, |
3bffc475f CAIF: fix indenta... |
190 191 |
enum caif_ctrlcmd flow, int phyid) |
bece7b239 caif: Rewritten s... |
192 193 |
{ struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); |
e6f95ec8d net-caif: add CAI... |
194 195 |
switch (flow) { case CAIF_CTRLCMD_FLOW_ON_IND: |
bece7b239 caif: Rewritten s... |
196 |
/* OK from modem to start sending again */ |
bece7b239 caif: Rewritten s... |
197 198 |
set_tx_flow_on(cf_sk); cf_sk->sk.sk_state_change(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
199 200 201 |
break; case CAIF_CTRLCMD_FLOW_OFF_IND: |
bece7b239 caif: Rewritten s... |
202 |
/* Modem asks us to shut up */ |
bece7b239 caif: Rewritten s... |
203 204 |
set_tx_flow_off(cf_sk); cf_sk->sk.sk_state_change(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
205 206 207 |
break; case CAIF_CTRLCMD_INIT_RSP: |
bece7b239 caif: Rewritten s... |
208 |
/* We're now connected */ |
b3ccfbe40 caif: Protected i... |
209 210 |
caif_client_register_refcnt(&cf_sk->layer, cfsk_hold, cfsk_put); |
bece7b239 caif: Rewritten s... |
211 212 |
cf_sk->sk.sk_state = CAIF_CONNECTED; set_tx_flow_on(cf_sk); |
eaa8c5f3c caif: Clear shutd... |
213 |
cf_sk->sk.sk_shutdown = 0; |
bece7b239 caif: Rewritten s... |
214 |
cf_sk->sk.sk_state_change(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
215 216 217 |
break; case CAIF_CTRLCMD_DEINIT_RSP: |
bece7b239 caif: Rewritten s... |
218 219 220 |
/* We're now disconnected */ cf_sk->sk.sk_state = CAIF_DISCONNECTED; cf_sk->sk.sk_state_change(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
221 222 223 |
break; case CAIF_CTRLCMD_INIT_FAIL_RSP: |
bece7b239 caif: Rewritten s... |
224 |
/* Connect request failed */ |
bece7b239 caif: Rewritten s... |
225 226 227 228 229 230 231 232 233 |
cf_sk->sk.sk_err = ECONNREFUSED; cf_sk->sk.sk_state = CAIF_DISCONNECTED; cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; /* * Socket "standards" seems to require POLLOUT to * be set at connect failure. */ set_tx_flow_on(cf_sk); cf_sk->sk.sk_state_change(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
234 235 236 |
break; case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND: |
bece7b239 caif: Rewritten s... |
237 |
/* Modem has closed this connection, or device is down. */ |
bece7b239 caif: Rewritten s... |
238 239 240 241 |
cf_sk->sk.sk_shutdown = SHUTDOWN_MASK; cf_sk->sk.sk_err = ECONNRESET; set_rx_flow_on(cf_sk); cf_sk->sk.sk_error_report(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
242 243 244 |
break; default: |
b31fa5bad net/caif: Use pr_fmt |
245 246 |
pr_debug("Unexpected flow command %d ", flow); |
e6f95ec8d net-caif: add CAI... |
247 248 |
} } |
bece7b239 caif: Rewritten s... |
249 |
static void caif_check_flow_release(struct sock *sk) |
e6f95ec8d net-caif: add CAI... |
250 |
{ |
bece7b239 caif: Rewritten s... |
251 |
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
e6f95ec8d net-caif: add CAI... |
252 |
|
bece7b239 caif: Rewritten s... |
253 254 |
if (rx_flow_is_on(cf_sk)) return; |
e6f95ec8d net-caif: add CAI... |
255 |
|
bece7b239 caif: Rewritten s... |
256 |
if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) { |
bece7b239 caif: Rewritten s... |
257 |
set_rx_flow_on(cf_sk); |
ca6a09f25 caif: Bugfix - Po... |
258 |
caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ); |
bece7b239 caif: Rewritten s... |
259 260 |
} } |
dcda138d2 caif: Bugfix - us... |
261 |
|
bece7b239 caif: Rewritten s... |
262 |
/* |
dcda138d2 caif: Bugfix - us... |
263 264 |
* Copied from unix_dgram_recvmsg, but removed credit checks, * changed locking, address handling and added MSG_TRUNC. |
bece7b239 caif: Rewritten s... |
265 |
*/ |
1b7841404 net: Remove iocb ... |
266 267 |
static int caif_seqpkt_recvmsg(struct socket *sock, struct msghdr *m, size_t len, int flags) |
e6f95ec8d net-caif: add CAI... |
268 269 270 |
{ struct sock *sk = sock->sk; |
e6f95ec8d net-caif: add CAI... |
271 |
struct sk_buff *skb; |
dcda138d2 caif: Bugfix - us... |
272 273 |
int ret; int copylen; |
e6f95ec8d net-caif: add CAI... |
274 |
|
dcda138d2 caif: Bugfix - us... |
275 |
ret = -EOPNOTSUPP; |
3eeff778e caif: fix MSG_OOB... |
276 |
if (flags & MSG_OOB) |
dcda138d2 caif: Bugfix - us... |
277 |
goto read_error; |
e6f95ec8d net-caif: add CAI... |
278 |
|
bece7b239 caif: Rewritten s... |
279 280 |
skb = skb_recv_datagram(sk, flags, 0 , &ret); if (!skb) |
e6f95ec8d net-caif: add CAI... |
281 |
goto read_error; |
dcda138d2 caif: Bugfix - us... |
282 283 284 285 |
copylen = skb->len; if (len < copylen) { m->msg_flags |= MSG_TRUNC; copylen = len; |
e6f95ec8d net-caif: add CAI... |
286 |
} |
51f3d02b9 net: Add and use ... |
287 |
ret = skb_copy_datagram_msg(skb, 0, m, copylen); |
bece7b239 caif: Rewritten s... |
288 |
if (ret) |
dcda138d2 caif: Bugfix - us... |
289 |
goto out_free; |
e6f95ec8d net-caif: add CAI... |
290 |
|
dcda138d2 caif: Bugfix - us... |
291 292 |
ret = (flags & MSG_TRUNC) ? skb->len : copylen; out_free: |
bece7b239 caif: Rewritten s... |
293 |
skb_free_datagram(sk, skb); |
bece7b239 caif: Rewritten s... |
294 |
caif_check_flow_release(sk); |
dcda138d2 caif: Bugfix - us... |
295 |
return ret; |
e6f95ec8d net-caif: add CAI... |
296 |
|
bece7b239 caif: Rewritten s... |
297 298 299 |
read_error: return ret; } |
e6f95ec8d net-caif: add CAI... |
300 |
|
e6f95ec8d net-caif: add CAI... |
301 |
|
bece7b239 caif: Rewritten s... |
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
/* Copied from unix_stream_wait_data, identical except for lock call. */ static long caif_stream_data_wait(struct sock *sk, long timeo) { DEFINE_WAIT(wait); lock_sock(sk); for (;;) { prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); if (!skb_queue_empty(&sk->sk_receive_queue) || sk->sk_err || sk->sk_state != CAIF_CONNECTED || sock_flag(sk, SOCK_DEAD) || (sk->sk_shutdown & RCV_SHUTDOWN) || signal_pending(current) || !timeo) break; |
e6f95ec8d net-caif: add CAI... |
319 |
|
9cd3e072b net: rename SOCK_... |
320 |
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
bece7b239 caif: Rewritten s... |
321 322 323 |
release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); |
b48732e4a unix/caif: sk_soc... |
324 325 326 |
if (sock_flag(sk, SOCK_DEAD)) break; |
9cd3e072b net: rename SOCK_... |
327 |
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); |
e6f95ec8d net-caif: add CAI... |
328 |
} |
bece7b239 caif: Rewritten s... |
329 330 331 332 |
finish_wait(sk_sleep(sk), &wait); release_sock(sk); return timeo; } |
e6f95ec8d net-caif: add CAI... |
333 |
|
bece7b239 caif: Rewritten s... |
334 335 336 337 |
/* * Copied from unix_stream_recvmsg, but removed credit checks, * changed locking calls, changed address handling. */ |
1b7841404 net: Remove iocb ... |
338 339 |
static int caif_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) |
bece7b239 caif: Rewritten s... |
340 341 342 343 344 345 |
{ struct sock *sk = sock->sk; int copied = 0; int target; int err = 0; long timeo; |
e6f95ec8d net-caif: add CAI... |
346 |
|
bece7b239 caif: Rewritten s... |
347 348 349 |
err = -EOPNOTSUPP; if (flags&MSG_OOB) goto out; |
e6f95ec8d net-caif: add CAI... |
350 |
|
bece7b239 caif: Rewritten s... |
351 352 353 354 355 356 357 |
/* * Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg */ err = -EAGAIN; if (sk->sk_state == CAIF_CONNECTING) goto out; |
e6f95ec8d net-caif: add CAI... |
358 |
|
bece7b239 caif: Rewritten s... |
359 360 361 |
caif_read_lock(sk); target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); |
e6f95ec8d net-caif: add CAI... |
362 |
|
bece7b239 caif: Rewritten s... |
363 364 365 |
do { int chunk; struct sk_buff *skb; |
e6f95ec8d net-caif: add CAI... |
366 |
|
bece7b239 caif: Rewritten s... |
367 |
lock_sock(sk); |
b48732e4a unix/caif: sk_soc... |
368 369 370 371 |
if (sock_flag(sk, SOCK_DEAD)) { err = -ECONNRESET; goto unlock; } |
bece7b239 caif: Rewritten s... |
372 373 |
skb = skb_dequeue(&sk->sk_receive_queue); caif_check_flow_release(sk); |
e6f95ec8d net-caif: add CAI... |
374 |
|
bece7b239 caif: Rewritten s... |
375 376 377 378 379 380 381 382 383 384 385 386 |
if (skb == NULL) { if (copied >= target) goto unlock; /* * POSIX 1003.1g mandates this order. */ err = sock_error(sk); if (err) goto unlock; err = -ECONNRESET; if (sk->sk_shutdown & RCV_SHUTDOWN) goto unlock; |
e6f95ec8d net-caif: add CAI... |
387 |
|
bece7b239 caif: Rewritten s... |
388 389 390 391 392 |
err = -EPIPE; if (sk->sk_state != CAIF_CONNECTED) goto unlock; if (sock_flag(sk, SOCK_DEAD)) goto unlock; |
e6f95ec8d net-caif: add CAI... |
393 |
|
bece7b239 caif: Rewritten s... |
394 |
release_sock(sk); |
e6f95ec8d net-caif: add CAI... |
395 |
|
bece7b239 caif: Rewritten s... |
396 397 398 |
err = -EAGAIN; if (!timeo) break; |
e6f95ec8d net-caif: add CAI... |
399 |
|
bece7b239 caif: Rewritten s... |
400 |
caif_read_unlock(sk); |
e6f95ec8d net-caif: add CAI... |
401 |
|
bece7b239 caif: Rewritten s... |
402 |
timeo = caif_stream_data_wait(sk, timeo); |
e6f95ec8d net-caif: add CAI... |
403 |
|
bece7b239 caif: Rewritten s... |
404 405 406 407 408 409 410 411 412 |
if (signal_pending(current)) { err = sock_intr_errno(timeo); goto out; } caif_read_lock(sk); continue; unlock: release_sock(sk); break; |
e6f95ec8d net-caif: add CAI... |
413 |
} |
bece7b239 caif: Rewritten s... |
414 415 |
release_sock(sk); chunk = min_t(unsigned int, skb->len, size); |
7eab8d9e8 new helper: memcp... |
416 |
if (memcpy_to_msg(msg, skb->data, chunk)) { |
bece7b239 caif: Rewritten s... |
417 418 419 420 421 422 423 |
skb_queue_head(&sk->sk_receive_queue, skb); if (copied == 0) copied = -EFAULT; break; } copied += chunk; size -= chunk; |
e6f95ec8d net-caif: add CAI... |
424 |
|
bece7b239 caif: Rewritten s... |
425 426 427 |
/* Mark read part of skb as used */ if (!(flags & MSG_PEEK)) { skb_pull(skb, chunk); |
e6f95ec8d net-caif: add CAI... |
428 |
|
bece7b239 caif: Rewritten s... |
429 430 431 432 433 434 |
/* put the skb back if we didn't use it up. */ if (skb->len) { skb_queue_head(&sk->sk_receive_queue, skb); break; } kfree_skb(skb); |
e6f95ec8d net-caif: add CAI... |
435 |
|
e6f95ec8d net-caif: add CAI... |
436 |
} else { |
bece7b239 caif: Rewritten s... |
437 438 439 440 441 442 |
/* * It is questionable, see note in unix_dgram_recvmsg. */ /* put message back and return */ skb_queue_head(&sk->sk_receive_queue, skb); break; |
e6f95ec8d net-caif: add CAI... |
443 |
} |
bece7b239 caif: Rewritten s... |
444 445 |
} while (size); caif_read_unlock(sk); |
e6f95ec8d net-caif: add CAI... |
446 |
|
bece7b239 caif: Rewritten s... |
447 448 449 |
out: return copied ? : err; } |
e6f95ec8d net-caif: add CAI... |
450 |
|
bece7b239 caif: Rewritten s... |
451 452 453 454 455 |
/* * Copied from sock.c:sock_wait_for_wmem, but change to wait for * CAIF flow-on and sock_writable. */ static long caif_wait_for_flow_on(struct caifsock *cf_sk, |
3bffc475f CAIF: fix indenta... |
456 |
int wait_writeable, long timeo, int *err) |
bece7b239 caif: Rewritten s... |
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
{ struct sock *sk = &cf_sk->sk; DEFINE_WAIT(wait); for (;;) { *err = 0; if (tx_flow_is_on(cf_sk) && (!wait_writeable || sock_writeable(&cf_sk->sk))) break; *err = -ETIMEDOUT; if (!timeo) break; *err = -ERESTARTSYS; if (signal_pending(current)) break; prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); *err = -ECONNRESET; if (sk->sk_shutdown & SHUTDOWN_MASK) break; *err = -sk->sk_err; if (sk->sk_err) break; *err = -EPIPE; if (cf_sk->sk.sk_state != CAIF_CONNECTED) break; timeo = schedule_timeout(timeo); |
e6f95ec8d net-caif: add CAI... |
482 |
} |
bece7b239 caif: Rewritten s... |
483 484 485 |
finish_wait(sk_sleep(sk), &wait); return timeo; } |
e6f95ec8d net-caif: add CAI... |
486 |
|
bece7b239 caif: Rewritten s... |
487 488 489 490 491 492 493 494 |
/* * Transmit a SKB. The device may temporarily request re-transmission * by returning EAGAIN. */ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, int noblock, long timeo) { struct cfpkt *pkt; |
e6f95ec8d net-caif: add CAI... |
495 |
|
bece7b239 caif: Rewritten s... |
496 |
pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); |
3f874adc4 caif: remove unes... |
497 |
memset(skb->cb, 0, sizeof(struct caif_payload_info)); |
447648128 caif: set traffic... |
498 |
cfpkt_set_prio(pkt, cf_sk->sk.sk_priority); |
e6f95ec8d net-caif: add CAI... |
499 |
|
ba7605745 caif: Bugfix doub... |
500 501 |
if (cf_sk->layer.dn == NULL) { kfree_skb(skb); |
4dd820c08 caif: Don't resen... |
502 |
return -EINVAL; |
ba7605745 caif: Bugfix doub... |
503 |
} |
e6f95ec8d net-caif: add CAI... |
504 |
|
4dd820c08 caif: Don't resen... |
505 |
return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); |
bece7b239 caif: Rewritten s... |
506 |
} |
e6f95ec8d net-caif: add CAI... |
507 |
|
bece7b239 caif: Rewritten s... |
508 |
/* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ |
1b7841404 net: Remove iocb ... |
509 510 |
static int caif_seqpkt_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
bece7b239 caif: Rewritten s... |
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
{ struct sock *sk = sock->sk; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); int buffer_size; int ret = 0; struct sk_buff *skb = NULL; int noblock; long timeo; caif_assert(cf_sk); ret = sock_error(sk); if (ret) goto err; ret = -EOPNOTSUPP; if (msg->msg_flags&MSG_OOB) goto err; ret = -EOPNOTSUPP; if (msg->msg_namelen) goto err; ret = -EINVAL; |
c0371da60 put iov_iter into... |
533 |
if (unlikely(msg->msg_iter.iov->iov_base == NULL)) |
bece7b239 caif: Rewritten s... |
534 535 |
goto err; noblock = msg->msg_flags & MSG_DONTWAIT; |
bece7b239 caif: Rewritten s... |
536 537 538 |
timeo = sock_sndtimeo(sk, noblock); timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), 1, timeo, &ret); |
2aa40aef9 caif: Use link la... |
539 540 |
if (ret) goto err; |
bece7b239 caif: Rewritten s... |
541 542 543 544 545 |
ret = -EPIPE; if (cf_sk->sk.sk_state != CAIF_CONNECTED || sock_flag(sk, SOCK_DEAD) || (sk->sk_shutdown & RCV_SHUTDOWN)) goto err; |
2aa40aef9 caif: Use link la... |
546 547 548 549 550 551 |
/* Error if trying to write more than maximum frame size. */ ret = -EMSGSIZE; if (len > cf_sk->maxframe && cf_sk->sk.sk_protocol != CAIFPROTO_RFM) goto err; buffer_size = len + cf_sk->headroom + cf_sk->tailroom; |
bece7b239 caif: Rewritten s... |
552 553 |
ret = -ENOMEM; skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); |
2aa40aef9 caif: Use link la... |
554 555 |
if (!skb || skb_tailroom(skb) < buffer_size) |
bece7b239 caif: Rewritten s... |
556 |
goto err; |
2aa40aef9 caif: Use link la... |
557 558 |
skb_reserve(skb, cf_sk->headroom); |
bece7b239 caif: Rewritten s... |
559 |
|
6ce8e9ce5 new helper: memcp... |
560 |
ret = memcpy_from_msg(skb_put(skb, len), msg, len); |
bece7b239 caif: Rewritten s... |
561 562 563 564 565 |
if (ret) goto err; ret = transmit_skb(skb, cf_sk, noblock, timeo); if (ret < 0) |
c85c2951d caif: Handle dev_... |
566 567 |
/* skb is already freed */ return ret; |
bece7b239 caif: Rewritten s... |
568 569 570 571 572 |
return len; err: kfree_skb(skb); return ret; } |
e6f95ec8d net-caif: add CAI... |
573 |
|
bece7b239 caif: Rewritten s... |
574 575 576 577 578 |
/* * Copied from unix_stream_sendmsg and adapted to CAIF: * Changed removed permission handling and added waiting for flow on * and other minor adaptations. */ |
1b7841404 net: Remove iocb ... |
579 580 |
static int caif_stream_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
bece7b239 caif: Rewritten s... |
581 582 583 584 585 586 587 |
{ struct sock *sk = sock->sk; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); int err, size; struct sk_buff *skb; int sent = 0; long timeo; |
e6f95ec8d net-caif: add CAI... |
588 |
|
bece7b239 caif: Rewritten s... |
589 |
err = -EOPNOTSUPP; |
bece7b239 caif: Rewritten s... |
590 591 |
if (unlikely(msg->msg_flags&MSG_OOB)) goto out_err; |
e6f95ec8d net-caif: add CAI... |
592 |
|
bece7b239 caif: Rewritten s... |
593 594 |
if (unlikely(msg->msg_namelen)) goto out_err; |
e6f95ec8d net-caif: add CAI... |
595 |
|
bece7b239 caif: Rewritten s... |
596 597 |
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); timeo = caif_wait_for_flow_on(cf_sk, 1, timeo, &err); |
e6f95ec8d net-caif: add CAI... |
598 |
|
bece7b239 caif: Rewritten s... |
599 600 |
if (unlikely(sk->sk_shutdown & SEND_SHUTDOWN)) goto pipe_err; |
e6f95ec8d net-caif: add CAI... |
601 |
|
bece7b239 caif: Rewritten s... |
602 |
while (sent < len) { |
e6f95ec8d net-caif: add CAI... |
603 |
|
bece7b239 caif: Rewritten s... |
604 |
size = len-sent; |
e6f95ec8d net-caif: add CAI... |
605 |
|
2aa40aef9 caif: Use link la... |
606 607 |
if (size > cf_sk->maxframe) size = cf_sk->maxframe; |
e6f95ec8d net-caif: add CAI... |
608 |
|
bece7b239 caif: Rewritten s... |
609 610 611 |
/* If size is more than half of sndbuf, chop up message */ if (size > ((sk->sk_sndbuf >> 1) - 64)) size = (sk->sk_sndbuf >> 1) - 64; |
e6f95ec8d net-caif: add CAI... |
612 |
|
bece7b239 caif: Rewritten s... |
613 614 |
if (size > SKB_MAX_ALLOC) size = SKB_MAX_ALLOC; |
e6f95ec8d net-caif: add CAI... |
615 |
|
bece7b239 caif: Rewritten s... |
616 |
skb = sock_alloc_send_skb(sk, |
2aa40aef9 caif: Use link la... |
617 618 |
size + cf_sk->headroom + cf_sk->tailroom, |
bece7b239 caif: Rewritten s... |
619 620 621 622 |
msg->msg_flags&MSG_DONTWAIT, &err); if (skb == NULL) goto out_err; |
e6f95ec8d net-caif: add CAI... |
623 |
|
2aa40aef9 caif: Use link la... |
624 |
skb_reserve(skb, cf_sk->headroom); |
bece7b239 caif: Rewritten s... |
625 626 627 628 629 630 631 632 |
/* * If you pass two values to the sock_alloc_send_skb * it tries to grab the large buffer with GFP_NOFS * (which can fail easily), and if it fails grab the * fallback size buffer which is under a page and will * succeed. [Alan] */ size = min_t(int, size, skb_tailroom(skb)); |
e6f95ec8d net-caif: add CAI... |
633 |
|
6ce8e9ce5 new helper: memcp... |
634 |
err = memcpy_from_msg(skb_put(skb, size), msg, size); |
bece7b239 caif: Rewritten s... |
635 636 637 638 639 640 |
if (err) { kfree_skb(skb); goto out_err; } err = transmit_skb(skb, cf_sk, msg->msg_flags&MSG_DONTWAIT, timeo); |
ba7605745 caif: Bugfix doub... |
641 642 |
if (err < 0) /* skb is already freed */ |
bece7b239 caif: Rewritten s... |
643 |
goto pipe_err; |
ba7605745 caif: Bugfix doub... |
644 |
|
bece7b239 caif: Rewritten s... |
645 |
sent += size; |
e6f95ec8d net-caif: add CAI... |
646 |
} |
e6f95ec8d net-caif: add CAI... |
647 |
|
bece7b239 caif: Rewritten s... |
648 |
return sent; |
e6f95ec8d net-caif: add CAI... |
649 |
|
bece7b239 caif: Rewritten s... |
650 651 652 653 654 655 |
pipe_err: if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL)) send_sig(SIGPIPE, current, 0); err = -EPIPE; out_err: return sent ? : err; |
e6f95ec8d net-caif: add CAI... |
656 |
} |
a7b75c5a8 net: pass a sockp... |
657 658 |
static int setsockopt(struct socket *sock, int lvl, int opt, sockptr_t ov, unsigned int ol) |
e6f95ec8d net-caif: add CAI... |
659 660 661 |
{ struct sock *sk = sock->sk; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
f2527ec43 caif: Bugfix for ... |
662 |
int linksel; |
e6f95ec8d net-caif: add CAI... |
663 |
|
bece7b239 caif: Rewritten s... |
664 |
if (cf_sk->sk.sk_socket->state != SS_UNCONNECTED) |
e6f95ec8d net-caif: add CAI... |
665 |
return -ENOPROTOOPT; |
bece7b239 caif: Rewritten s... |
666 |
|
e6f95ec8d net-caif: add CAI... |
667 668 |
switch (opt) { case CAIFSO_LINK_SELECT: |
bece7b239 caif: Rewritten s... |
669 |
if (ol < sizeof(int)) |
e6f95ec8d net-caif: add CAI... |
670 |
return -EINVAL; |
e6f95ec8d net-caif: add CAI... |
671 672 |
if (lvl != SOL_CAIF) goto bad_sol; |
a7b75c5a8 net: pass a sockp... |
673 |
if (copy_from_sockptr(&linksel, ov, sizeof(int))) |
e6f95ec8d net-caif: add CAI... |
674 675 676 677 678 |
return -EINVAL; lock_sock(&(cf_sk->sk)); cf_sk->conn_req.link_selector = linksel; release_sock(&cf_sk->sk); return 0; |
e6f95ec8d net-caif: add CAI... |
679 680 681 682 683 |
case CAIFSO_REQ_PARAM: if (lvl != SOL_CAIF) goto bad_sol; if (cf_sk->sk.sk_protocol != CAIFPROTO_UTIL) return -ENOPROTOOPT; |
e6f95ec8d net-caif: add CAI... |
684 |
lock_sock(&(cf_sk->sk)); |
bece7b239 caif: Rewritten s... |
685 |
if (ol > sizeof(cf_sk->conn_req.param.data) || |
a7b75c5a8 net: pass a sockp... |
686 |
copy_from_sockptr(&cf_sk->conn_req.param.data, ov, ol)) { |
e6f95ec8d net-caif: add CAI... |
687 |
release_sock(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
688 689 |
return -EINVAL; } |
91b5c98c2 caif: don't set c... |
690 |
cf_sk->conn_req.param.size = ol; |
e6f95ec8d net-caif: add CAI... |
691 692 693 694 |
release_sock(&cf_sk->sk); return 0; default: |
bece7b239 caif: Rewritten s... |
695 |
return -ENOPROTOOPT; |
e6f95ec8d net-caif: add CAI... |
696 697 698 699 |
} return 0; bad_sol: |
e6f95ec8d net-caif: add CAI... |
700 701 702 |
return -ENOPROTOOPT; } |
bece7b239 caif: Rewritten s... |
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 |
/* * caif_connect() - Connect a CAIF Socket * Copied and modified af_irda.c:irda_connect(). * * Note : by consulting "errno", the user space caller may learn the cause * of the failure. Most of them are visible in the function, others may come * from subroutines called and are listed here : * o -EAFNOSUPPORT: bad socket family or type. * o -ESOCKTNOSUPPORT: bad socket type or protocol * o -EINVAL: bad socket address, or CAIF link type * o -ECONNREFUSED: remote end refused the connection. * o -EINPROGRESS: connect request sent but timed out (or non-blocking) * o -EISCONN: already connected. * o -ETIMEDOUT: Connection timed out (send timeout) * o -ENODEV: No link layer to send request * o -ECONNRESET: Received Shutdown indication or lost link layer * o -ENOMEM: Out of memory * * State Strategy: * o sk_state: holds the CAIF_* protocol state, it's updated by * caif_ctrl_cb. * o sock->state: holds the SS_* socket state and is updated by connect and * disconnect. */ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) |
e6f95ec8d net-caif: add CAI... |
729 |
{ |
e6f95ec8d net-caif: add CAI... |
730 |
struct sock *sk = sock->sk; |
bece7b239 caif: Rewritten s... |
731 732 733 |
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); long timeo; int err; |
2aa40aef9 caif: Use link la... |
734 |
int ifindex, headroom, tailroom; |
79315068f caif: fix two cai... |
735 |
unsigned int mtu; |
2aa40aef9 caif: Use link la... |
736 |
struct net_device *dev; |
bece7b239 caif: Rewritten s... |
737 |
lock_sock(sk); |
e6f95ec8d net-caif: add CAI... |
738 |
|
20a3d5bf5 caif: Add sockadd... |
739 740 741 |
err = -EINVAL; if (addr_len < offsetofend(struct sockaddr, sa_family)) goto out; |
bece7b239 caif: Rewritten s... |
742 743 |
err = -EAFNOSUPPORT; if (uaddr->sa_family != AF_CAIF) |
e6f95ec8d net-caif: add CAI... |
744 |
goto out; |
bece7b239 caif: Rewritten s... |
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 |
switch (sock->state) { case SS_UNCONNECTED: /* Normal case, a fresh connect */ caif_assert(sk->sk_state == CAIF_DISCONNECTED); break; case SS_CONNECTING: switch (sk->sk_state) { case CAIF_CONNECTED: sock->state = SS_CONNECTED; err = -EISCONN; goto out; case CAIF_DISCONNECTED: /* Reconnect allowed */ break; case CAIF_CONNECTING: err = -EALREADY; if (flags & O_NONBLOCK) goto out; goto wait_connect; } break; case SS_CONNECTED: caif_assert(sk->sk_state == CAIF_CONNECTED || sk->sk_state == CAIF_DISCONNECTED); if (sk->sk_shutdown & SHUTDOWN_MASK) { /* Allow re-connect after SHUTDOWN_IND */ |
bee925db9 caif: prepare sup... |
771 |
caif_disconnect_client(sock_net(sk), &cf_sk->layer); |
54e90fb5c caif: Fixes freez... |
772 |
caif_free_client(&cf_sk->layer); |
bece7b239 caif: Rewritten s... |
773 774 775 776 777 778 779 780 781 |
break; } /* No reconnect on a seqpacket socket */ err = -EISCONN; goto out; case SS_DISCONNECTING: case SS_FREE: caif_assert(1); /*Should never happen */ break; |
e6f95ec8d net-caif: add CAI... |
782 |
} |
bece7b239 caif: Rewritten s... |
783 784 785 |
sk->sk_state = CAIF_DISCONNECTED; sock->state = SS_UNCONNECTED; sk_stream_kill_queues(&cf_sk->sk); |
e6f95ec8d net-caif: add CAI... |
786 |
|
bece7b239 caif: Rewritten s... |
787 |
err = -EINVAL; |
f5d72af9f caif: remove unne... |
788 |
if (addr_len != sizeof(struct sockaddr_caif)) |
bece7b239 caif: Rewritten s... |
789 |
goto out; |
e6f95ec8d net-caif: add CAI... |
790 |
|
bece7b239 caif: Rewritten s... |
791 |
memcpy(&cf_sk->conn_req.sockaddr, uaddr, |
e6f95ec8d net-caif: add CAI... |
792 |
sizeof(struct sockaddr_caif)); |
bece7b239 caif: Rewritten s... |
793 794 795 |
/* Move to connecting socket, start sending Connect Requests */ sock->state = SS_CONNECTING; sk->sk_state = CAIF_CONNECTING; |
33b2f5598 caif: Bugfix debu... |
796 |
/* Check priority value comming from socket */ |
f2527ec43 caif: Bugfix for ... |
797 798 799 800 801 802 803 804 805 806 |
/* if priority value is out of range it will be ajusted */ if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) cf_sk->conn_req.priority = CAIF_PRIO_MAX; else if (cf_sk->sk.sk_priority < CAIF_PRIO_MIN) cf_sk->conn_req.priority = CAIF_PRIO_MIN; else cf_sk->conn_req.priority = cf_sk->sk.sk_priority; /*ifindex = id of the interface.*/ cf_sk->conn_req.ifindex = cf_sk->sk.sk_bound_dev_if; |
bece7b239 caif: Rewritten s... |
807 |
cf_sk->layer.receive = caif_sktrecv_cb; |
b3ccfbe40 caif: Protected i... |
808 |
|
bee925db9 caif: prepare sup... |
809 |
err = caif_connect_client(sock_net(sk), &cf_sk->conn_req, |
2aa40aef9 caif: Use link la... |
810 |
&cf_sk->layer, &ifindex, &headroom, &tailroom); |
b3ccfbe40 caif: Protected i... |
811 |
|
bece7b239 caif: Rewritten s... |
812 813 814 815 |
if (err < 0) { cf_sk->sk.sk_socket->state = SS_UNCONNECTED; cf_sk->sk.sk_state = CAIF_DISCONNECTED; goto out; |
e6f95ec8d net-caif: add CAI... |
816 |
} |
79315068f caif: fix two cai... |
817 818 819 820 821 822 823 824 |
err = -ENODEV; rcu_read_lock(); dev = dev_get_by_index_rcu(sock_net(sk), ifindex); if (!dev) { rcu_read_unlock(); goto out; } |
2aa40aef9 caif: Use link la... |
825 |
cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom); |
79315068f caif: fix two cai... |
826 827 |
mtu = dev->mtu; rcu_read_unlock(); |
2aa40aef9 caif: Use link la... |
828 |
cf_sk->tailroom = tailroom; |
79315068f caif: fix two cai... |
829 |
cf_sk->maxframe = mtu - (headroom + tailroom); |
2aa40aef9 caif: Use link la... |
830 |
if (cf_sk->maxframe < 1) { |
b31fa5bad net/caif: Use pr_fmt |
831 832 |
pr_warn("CAIF Interface MTU too small (%d) ", dev->mtu); |
f2527ec43 caif: Bugfix for ... |
833 |
err = -ENODEV; |
2aa40aef9 caif: Use link la... |
834 835 |
goto out; } |
e6f95ec8d net-caif: add CAI... |
836 |
|
bece7b239 caif: Rewritten s... |
837 838 |
err = -EINPROGRESS; wait_connect: |
e6f95ec8d net-caif: add CAI... |
839 |
|
bece7b239 caif: Rewritten s... |
840 841 |
if (sk->sk_state != CAIF_CONNECTED && (flags & O_NONBLOCK)) goto out; |
e6f95ec8d net-caif: add CAI... |
842 |
|
bece7b239 caif: Rewritten s... |
843 844 845 |
timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); release_sock(sk); |
9e4b816bc caif: Bugfix - wa... |
846 847 |
err = -ERESTARTSYS; timeo = wait_event_interruptible_timeout(*sk_sleep(sk), |
bece7b239 caif: Rewritten s... |
848 849 850 |
sk->sk_state != CAIF_CONNECTING, timeo); lock_sock(sk); |
9e4b816bc caif: Bugfix - wa... |
851 |
if (timeo < 0) |
bece7b239 caif: Rewritten s... |
852 |
goto out; /* -ERESTARTSYS */ |
e6f95ec8d net-caif: add CAI... |
853 |
|
9e4b816bc caif: Bugfix - wa... |
854 855 856 |
err = -ETIMEDOUT; if (timeo == 0 && sk->sk_state != CAIF_CONNECTED) goto out; |
bece7b239 caif: Rewritten s... |
857 858 859 860 861 862 863 864 865 |
if (sk->sk_state != CAIF_CONNECTED) { sock->state = SS_UNCONNECTED; err = sock_error(sk); if (!err) err = -ECONNREFUSED; goto out; } sock->state = SS_CONNECTED; err = 0; |
e6f95ec8d net-caif: add CAI... |
866 |
out: |
bece7b239 caif: Rewritten s... |
867 868 |
release_sock(sk); return err; |
e6f95ec8d net-caif: add CAI... |
869 |
} |
bece7b239 caif: Rewritten s... |
870 871 872 873 874 |
/* * caif_release() - Disconnect a CAIF Socket * Copied and modified af_irda.c:irda_release(). */ static int caif_release(struct socket *sock) |
e6f95ec8d net-caif: add CAI... |
875 |
{ |
e6f95ec8d net-caif: add CAI... |
876 |
struct sock *sk = sock->sk; |
bece7b239 caif: Rewritten s... |
877 |
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
e6f95ec8d net-caif: add CAI... |
878 |
|
bece7b239 caif: Rewritten s... |
879 880 |
if (!sk) return 0; |
e6f95ec8d net-caif: add CAI... |
881 |
|
bece7b239 caif: Rewritten s... |
882 |
set_tx_flow_off(cf_sk); |
e6f95ec8d net-caif: add CAI... |
883 884 |
/* |
bece7b239 caif: Rewritten s... |
885 886 887 |
* Ensure that packets are not queued after this point in time. * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, * this ensures no packets when sock is dead. |
e6f95ec8d net-caif: add CAI... |
888 |
*/ |
c85c2951d caif: Handle dev_... |
889 |
spin_lock_bh(&sk->sk_receive_queue.lock); |
bece7b239 caif: Rewritten s... |
890 |
sock_set_flag(sk, SOCK_DEAD); |
c85c2951d caif: Handle dev_... |
891 |
spin_unlock_bh(&sk->sk_receive_queue.lock); |
bece7b239 caif: Rewritten s... |
892 |
sock->sk = NULL; |
e6f95ec8d net-caif: add CAI... |
893 |
|
33b2f5598 caif: Bugfix debu... |
894 |
WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir)); |
fb0d164cc net/caif/caif_soc... |
895 |
debugfs_remove_recursive(cf_sk->debugfs_socket_dir); |
e6f95ec8d net-caif: add CAI... |
896 |
|
e6f95ec8d net-caif: add CAI... |
897 |
lock_sock(&(cf_sk->sk)); |
bece7b239 caif: Rewritten s... |
898 899 |
sk->sk_state = CAIF_DISCONNECTED; sk->sk_shutdown = SHUTDOWN_MASK; |
e6f95ec8d net-caif: add CAI... |
900 |
|
54e90fb5c caif: Fixes freez... |
901 |
caif_disconnect_client(sock_net(sk), &cf_sk->layer); |
bece7b239 caif: Rewritten s... |
902 |
cf_sk->sk.sk_socket->state = SS_DISCONNECTING; |
a9a08845e vfs: do bulk POLL... |
903 |
wake_up_interruptible_poll(sk_sleep(sk), EPOLLERR|EPOLLHUP); |
e6f95ec8d net-caif: add CAI... |
904 |
|
bece7b239 caif: Rewritten s... |
905 |
sock_orphan(sk); |
bece7b239 caif: Rewritten s... |
906 907 908 |
sk_stream_kill_queues(&cf_sk->sk); release_sock(sk); sock_put(sk); |
54e90fb5c caif: Fixes freez... |
909 |
return 0; |
bece7b239 caif: Rewritten s... |
910 |
} |
e6f95ec8d net-caif: add CAI... |
911 |
|
bece7b239 caif: Rewritten s... |
912 |
/* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */ |
a11e1d432 Revert changes to... |
913 914 |
static __poll_t caif_poll(struct file *file, struct socket *sock, poll_table *wait) |
bece7b239 caif: Rewritten s... |
915 916 |
{ struct sock *sk = sock->sk; |
a11e1d432 Revert changes to... |
917 |
__poll_t mask; |
bece7b239 caif: Rewritten s... |
918 |
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
a11e1d432 Revert changes to... |
919 |
|
89ab066d4 Revert "net: simp... |
920 |
sock_poll_wait(file, sock, wait); |
a11e1d432 Revert changes to... |
921 |
mask = 0; |
e6f95ec8d net-caif: add CAI... |
922 |
|
bece7b239 caif: Rewritten s... |
923 924 |
/* exceptional events? */ if (sk->sk_err) |
a9a08845e vfs: do bulk POLL... |
925 |
mask |= EPOLLERR; |
bece7b239 caif: Rewritten s... |
926 |
if (sk->sk_shutdown == SHUTDOWN_MASK) |
a9a08845e vfs: do bulk POLL... |
927 |
mask |= EPOLLHUP; |
bece7b239 caif: Rewritten s... |
928 |
if (sk->sk_shutdown & RCV_SHUTDOWN) |
a9a08845e vfs: do bulk POLL... |
929 |
mask |= EPOLLRDHUP; |
e6f95ec8d net-caif: add CAI... |
930 |
|
bece7b239 caif: Rewritten s... |
931 |
/* readable? */ |
3ef7cf57c net: use skb_queu... |
932 |
if (!skb_queue_empty_lockless(&sk->sk_receive_queue) || |
bece7b239 caif: Rewritten s... |
933 |
(sk->sk_shutdown & RCV_SHUTDOWN)) |
a9a08845e vfs: do bulk POLL... |
934 |
mask |= EPOLLIN | EPOLLRDNORM; |
e6f95ec8d net-caif: add CAI... |
935 |
|
e6f95ec8d net-caif: add CAI... |
936 |
/* |
bece7b239 caif: Rewritten s... |
937 938 |
* we set writable also when the other side has shut down the * connection. This prevents stuck sockets. |
e6f95ec8d net-caif: add CAI... |
939 |
*/ |
bece7b239 caif: Rewritten s... |
940 |
if (sock_writeable(sk) && tx_flow_is_on(cf_sk)) |
a9a08845e vfs: do bulk POLL... |
941 |
mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND; |
bece7b239 caif: Rewritten s... |
942 943 |
return mask; |
e6f95ec8d net-caif: add CAI... |
944 |
} |
bece7b239 caif: Rewritten s... |
945 946 947 948 949 950 951 952 953 |
static const struct proto_ops caif_seqpacket_ops = { .family = PF_CAIF, .owner = THIS_MODULE, .release = caif_release, .bind = sock_no_bind, .connect = caif_connect, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = sock_no_getname, |
a11e1d432 Revert changes to... |
954 |
.poll = caif_poll, |
bece7b239 caif: Rewritten s... |
955 956 957 958 |
.ioctl = sock_no_ioctl, .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = setsockopt, |
bece7b239 caif: Rewritten s... |
959 960 961 962 963 964 965 |
.sendmsg = caif_seqpkt_sendmsg, .recvmsg = caif_seqpkt_recvmsg, .mmap = sock_no_mmap, .sendpage = sock_no_sendpage, }; static const struct proto_ops caif_stream_ops = { |
e6f95ec8d net-caif: add CAI... |
966 967 968 969 970 971 972 973 |
.family = PF_CAIF, .owner = THIS_MODULE, .release = caif_release, .bind = sock_no_bind, .connect = caif_connect, .socketpair = sock_no_socketpair, .accept = sock_no_accept, .getname = sock_no_getname, |
a11e1d432 Revert changes to... |
974 |
.poll = caif_poll, |
e6f95ec8d net-caif: add CAI... |
975 976 |
.ioctl = sock_no_ioctl, .listen = sock_no_listen, |
bece7b239 caif: Rewritten s... |
977 |
.shutdown = sock_no_shutdown, |
e6f95ec8d net-caif: add CAI... |
978 |
.setsockopt = setsockopt, |
bece7b239 caif: Rewritten s... |
979 980 |
.sendmsg = caif_stream_sendmsg, .recvmsg = caif_stream_recvmsg, |
e6f95ec8d net-caif: add CAI... |
981 |
.mmap = sock_no_mmap, |
bece7b239 caif: Rewritten s... |
982 |
.sendpage = sock_no_sendpage, |
e6f95ec8d net-caif: add CAI... |
983 984 985 986 987 |
}; /* This function is called when a socket is finally destroyed. */ static void caif_sock_destructor(struct sock *sk) { |
bece7b239 caif: Rewritten s... |
988 |
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
14afee4b6 net: convert sock... |
989 |
caif_assert(!refcount_read(&sk->sk_wmem_alloc)); |
e6f95ec8d net-caif: add CAI... |
990 991 992 |
caif_assert(sk_unhashed(sk)); caif_assert(!sk->sk_socket); if (!sock_flag(sk, SOCK_DEAD)) { |
33b2f5598 caif: Bugfix debu... |
993 994 |
pr_debug("Attempt to release alive CAIF socket: %p ", sk); |
e6f95ec8d net-caif: add CAI... |
995 996 |
return; } |
bece7b239 caif: Rewritten s... |
997 |
sk_stream_kill_queues(&cf_sk->sk); |
b3ccfbe40 caif: Protected i... |
998 |
caif_free_client(&cf_sk->layer); |
e6f95ec8d net-caif: add CAI... |
999 1000 1001 |
} static int caif_create(struct net *net, struct socket *sock, int protocol, |
3bffc475f CAIF: fix indenta... |
1002 |
int kern) |
e6f95ec8d net-caif: add CAI... |
1003 1004 1005 |
{ struct sock *sk = NULL; struct caifsock *cf_sk = NULL; |
e6f95ec8d net-caif: add CAI... |
1006 1007 1008 |
static struct proto prot = {.name = "PF_CAIF", .owner = THIS_MODULE, .obj_size = sizeof(struct caifsock), |
93070d339 caif: Define user... |
1009 1010 |
.useroffset = offsetof(struct caifsock, conn_req.param), .usersize = sizeof_field(struct caifsock, conn_req.param) |
e6f95ec8d net-caif: add CAI... |
1011 |
}; |
bece7b239 caif: Rewritten s... |
1012 1013 |
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN)) return -EPERM; |
e6f95ec8d net-caif: add CAI... |
1014 1015 |
/* * The sock->type specifies the socket type to use. |
bece7b239 caif: Rewritten s... |
1016 1017 1018 |
* The CAIF socket is a packet stream in the sense * that it is packet based. CAIF trusts the reliability * of the link, no resending is implemented. |
e6f95ec8d net-caif: add CAI... |
1019 |
*/ |
bece7b239 caif: Rewritten s... |
1020 1021 1022 1023 1024 |
if (sock->type == SOCK_SEQPACKET) sock->ops = &caif_seqpacket_ops; else if (sock->type == SOCK_STREAM) sock->ops = &caif_stream_ops; else |
e6f95ec8d net-caif: add CAI... |
1025 |
return -ESOCKTNOSUPPORT; |
e6f95ec8d net-caif: add CAI... |
1026 1027 1028 |
if (protocol < 0 || protocol >= CAIFPROTO_MAX) return -EPROTONOSUPPORT; /* |
bece7b239 caif: Rewritten s... |
1029 1030 |
* Set the socket state to unconnected. The socket state * is really not used at all in the net/core or socket.c but the |
e6f95ec8d net-caif: add CAI... |
1031 1032 |
* initialization makes sure that sock->state is not uninitialized. */ |
11aa9c28b net: Pass kern fr... |
1033 |
sk = sk_alloc(net, PF_CAIF, GFP_KERNEL, &prot, kern); |
e6f95ec8d net-caif: add CAI... |
1034 1035 1036 1037 1038 1039 1040 |
if (!sk) return -ENOMEM; cf_sk = container_of(sk, struct caifsock, sk); /* Store the protocol */ sk->sk_protocol = (unsigned char) protocol; |
447648128 caif: set traffic... |
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 |
/* Initialize default priority for well-known cases */ switch (protocol) { case CAIFPROTO_AT: sk->sk_priority = TC_PRIO_CONTROL; break; case CAIFPROTO_RFM: sk->sk_priority = TC_PRIO_INTERACTIVE_BULK; break; default: sk->sk_priority = TC_PRIO_BESTEFFORT; } |
e6f95ec8d net-caif: add CAI... |
1052 1053 1054 1055 1056 1057 1058 1059 |
/* * Lock in order to try to stop someone from opening the socket * too early. */ lock_sock(&(cf_sk->sk)); /* Initialize the nozero default sock structure data. */ sock_init_data(sock, sk); |
e6f95ec8d net-caif: add CAI... |
1060 |
sk->sk_destruct = caif_sock_destructor; |
e6f95ec8d net-caif: add CAI... |
1061 |
|
bece7b239 caif: Rewritten s... |
1062 1063 1064 1065 |
mutex_init(&cf_sk->readlock); /* single task reading lock */ cf_sk->layer.ctrlcmd = caif_ctrl_cb; cf_sk->sk.sk_socket->state = SS_UNCONNECTED; cf_sk->sk.sk_state = CAIF_DISCONNECTED; |
e6f95ec8d net-caif: add CAI... |
1066 |
|
bece7b239 caif: Rewritten s... |
1067 1068 |
set_tx_flow_off(cf_sk); set_rx_flow_on(cf_sk); |
e6f95ec8d net-caif: add CAI... |
1069 1070 |
/* Set default options on configuration */ |
bece7b239 caif: Rewritten s... |
1071 |
cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; |
e6f95ec8d net-caif: add CAI... |
1072 |
cf_sk->conn_req.protocol = protocol; |
e6f95ec8d net-caif: add CAI... |
1073 1074 |
release_sock(&cf_sk->sk); return 0; |
e6f95ec8d net-caif: add CAI... |
1075 |
} |
bece7b239 caif: Rewritten s... |
1076 |
|
173e7837a net: socket: mark... |
1077 |
static const struct net_proto_family caif_family_ops = { |
e6f95ec8d net-caif: add CAI... |
1078 1079 1080 1081 |
.family = PF_CAIF, .create = caif_create, .owner = THIS_MODULE, }; |
4a695823b caif: Kill debugf... |
1082 |
static int __init caif_sktinit_module(void) |
e6f95ec8d net-caif: add CAI... |
1083 |
{ |
c79e167c3 net: caif: remove... |
1084 |
return sock_register(&caif_family_ops); |
e6f95ec8d net-caif: add CAI... |
1085 |
} |
e6f95ec8d net-caif: add CAI... |
1086 1087 1088 |
static void __exit caif_sktexit_module(void) { sock_unregister(PF_CAIF); |
e6f95ec8d net-caif: add CAI... |
1089 |
} |
e6f95ec8d net-caif: add CAI... |
1090 1091 |
module_init(caif_sktinit_module); module_exit(caif_sktexit_module); |