aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet/socket.c')
-rw-r--r--net/phonet/socket.c102
1 files changed, 40 insertions, 62 deletions
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 1eccfc35bcc0..b1adafab377c 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -225,15 +225,18 @@ static int pn_socket_autobind(struct socket *sock)
225 return 0; /* socket was already bound */ 225 return 0; /* socket was already bound */
226} 226}
227 227
228#ifdef CONFIG_PHONET_PIPECTRLR
229static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, 228static int pn_socket_connect(struct socket *sock, struct sockaddr *addr,
230 int len, int flags) 229 int len, int flags)
231{ 230{
232 struct sock *sk = sock->sk; 231 struct sock *sk = sock->sk;
232 struct pn_sock *pn = pn_sk(sk);
233 struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; 233 struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
234 long timeo; 234 struct task_struct *tsk = current;
235 long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
235 int err; 236 int err;
236 237
238 if (pn_socket_autobind(sock))
239 return -ENOBUFS;
237 if (len < sizeof(struct sockaddr_pn)) 240 if (len < sizeof(struct sockaddr_pn))
238 return -EINVAL; 241 return -EINVAL;
239 if (spn->spn_family != AF_PHONET) 242 if (spn->spn_family != AF_PHONET)
@@ -243,82 +246,61 @@ static int pn_socket_connect(struct socket *sock, struct sockaddr *addr,
243 246
244 switch (sock->state) { 247 switch (sock->state) {
245 case SS_UNCONNECTED: 248 case SS_UNCONNECTED:
246 sk->sk_state = TCP_CLOSE; 249 if (sk->sk_state != TCP_CLOSE) {
247 break;
248 case SS_CONNECTING:
249 switch (sk->sk_state) {
250 case TCP_SYN_RECV:
251 sock->state = SS_CONNECTED;
252 err = -EISCONN;
253 goto out;
254 case TCP_CLOSE:
255 err = -EALREADY;
256 if (flags & O_NONBLOCK)
257 goto out;
258 goto wait_connect;
259 }
260 break;
261 case SS_CONNECTED:
262 switch (sk->sk_state) {
263 case TCP_SYN_RECV:
264 err = -EISCONN; 250 err = -EISCONN;
265 goto out; 251 goto out;
266 case TCP_CLOSE:
267 sock->state = SS_UNCONNECTED;
268 break;
269 } 252 }
270 break; 253 break;
271 case SS_DISCONNECTING: 254 case SS_CONNECTING:
272 case SS_FREE: 255 err = -EALREADY;
273 break; 256 goto out;
257 default:
258 err = -EISCONN;
259 goto out;
274 } 260 }
275 sk->sk_state = TCP_CLOSE;
276 sk_stream_kill_queues(sk);
277 261
262 pn->dobject = pn_sockaddr_get_object(spn);
263 pn->resource = pn_sockaddr_get_resource(spn);
278 sock->state = SS_CONNECTING; 264 sock->state = SS_CONNECTING;
265
279 err = sk->sk_prot->connect(sk, addr, len); 266 err = sk->sk_prot->connect(sk, addr, len);
280 if (err < 0) { 267 if (err) {
281 sock->state = SS_UNCONNECTED; 268 sock->state = SS_UNCONNECTED;
282 sk->sk_state = TCP_CLOSE; 269 pn->dobject = 0;
283 goto out; 270 goto out;
284 } 271 }
285 272
286 err = -EINPROGRESS; 273 while (sk->sk_state == TCP_SYN_SENT) {
287wait_connect: 274 DEFINE_WAIT(wait);
288 if (sk->sk_state != TCP_SYN_RECV && (flags & O_NONBLOCK))
289 goto out;
290
291 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
292 release_sock(sk);
293 275
294 err = -ERESTARTSYS; 276 if (!timeo) {
295 timeo = wait_event_interruptible_timeout(*sk_sleep(sk), 277 err = -EINPROGRESS;
296 sk->sk_state != TCP_CLOSE, 278 goto out;
297 timeo); 279 }
298 280 if (signal_pending(tsk)) {
299 lock_sock(sk); 281 err = sock_intr_errno(timeo);
300 if (timeo < 0) 282 goto out;
301 goto out; /* -ERESTARTSYS */ 283 }
302
303 err = -ETIMEDOUT;
304 if (timeo == 0 && sk->sk_state != TCP_SYN_RECV)
305 goto out;
306 284
307 if (sk->sk_state != TCP_SYN_RECV) { 285 prepare_to_wait_exclusive(sk_sleep(sk), &wait,
308 sock->state = SS_UNCONNECTED; 286 TASK_INTERRUPTIBLE);
309 err = sock_error(sk); 287 release_sock(sk);
310 if (!err) 288 timeo = schedule_timeout(timeo);
311 err = -ECONNREFUSED; 289 lock_sock(sk);
312 goto out; 290 finish_wait(sk_sleep(sk), &wait);
313 } 291 }
314 sock->state = SS_CONNECTED;
315 err = 0;
316 292
293 if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED))
294 err = 0;
295 else if (sk->sk_state == TCP_CLOSE_WAIT)
296 err = -ECONNRESET;
297 else
298 err = -ECONNREFUSED;
299 sock->state = err ? SS_UNCONNECTED : SS_CONNECTED;
317out: 300out:
318 release_sock(sk); 301 release_sock(sk);
319 return err; 302 return err;
320} 303}
321#endif
322 304
323static int pn_socket_accept(struct socket *sock, struct socket *newsock, 305static int pn_socket_accept(struct socket *sock, struct socket *newsock,
324 int flags) 306 int flags)
@@ -486,11 +468,7 @@ const struct proto_ops phonet_stream_ops = {
486 .owner = THIS_MODULE, 468 .owner = THIS_MODULE,
487 .release = pn_socket_release, 469 .release = pn_socket_release,
488 .bind = pn_socket_bind, 470 .bind = pn_socket_bind,
489#ifdef CONFIG_PHONET_PIPECTRLR
490 .connect = pn_socket_connect, 471 .connect = pn_socket_connect,
491#else
492 .connect = sock_no_connect,
493#endif
494 .socketpair = sock_no_socketpair, 472 .socketpair = sock_no_socketpair,
495 .accept = pn_socket_accept, 473 .accept = pn_socket_accept,
496 .getname = pn_socket_getname, 474 .getname = pn_socket_getname,