diff options
author | Kumar Sanghvi <kumar.sanghvi@stericsson.com> | 2010-10-12 16:14:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-13 17:40:34 -0400 |
commit | b3d6255388de0680a14f0907deb7b7f4fa0d25d5 (patch) | |
tree | 8eaefeadef047a8bc6fcc269669ac4288e41ef64 /net/phonet/socket.c | |
parent | 7368ddf144afd79456fd853fa25f33e31da003a9 (diff) |
Phonet: 'connect' socket implementation for Pipe controller
Based on suggestion by Rémi Denis-Courmont to implement 'connect'
for Pipe controller logic, this patch implements 'connect' socket
call for the Pipe controller logic.
The patch does following:-
- Removes setsockopts for PNPIPE_CREATE and PNPIPE_DESTROY
- Adds setsockopt for setting the Pipe handle value
- Implements connect socket call
- Updates the Pipe controller logic
User-space should now follow below sequence with Pipe controller:-
-socket
-bind
-setsockopt for PNPIPE_PIPE_HANDLE
-connect
-setsockopt for PNPIPE_ENCAP_IP
-setsockopt for PNPIPE_ENABLE
GPRS/3G data has been tested working fine with this.
Signed-off-by: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
Acked-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/phonet/socket.c')
-rw-r--r-- | net/phonet/socket.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index aca8fba099e9..25f746d20c1f 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -225,6 +225,101 @@ 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 | ||
229 | static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, | ||
230 | int len, int flags) | ||
231 | { | ||
232 | struct sock *sk = sock->sk; | ||
233 | struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; | ||
234 | long timeo; | ||
235 | int err; | ||
236 | |||
237 | if (len < sizeof(struct sockaddr_pn)) | ||
238 | return -EINVAL; | ||
239 | if (spn->spn_family != AF_PHONET) | ||
240 | return -EAFNOSUPPORT; | ||
241 | |||
242 | lock_sock(sk); | ||
243 | |||
244 | switch (sock->state) { | ||
245 | case SS_UNCONNECTED: | ||
246 | 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; | ||
265 | goto out; | ||
266 | case TCP_CLOSE: | ||
267 | sock->state = SS_UNCONNECTED; | ||
268 | break; | ||
269 | } | ||
270 | break; | ||
271 | case SS_DISCONNECTING: | ||
272 | case SS_FREE: | ||
273 | break; | ||
274 | } | ||
275 | sk->sk_state = TCP_CLOSE; | ||
276 | sk_stream_kill_queues(sk); | ||
277 | |||
278 | sock->state = SS_CONNECTING; | ||
279 | err = sk->sk_prot->connect(sk, addr, len); | ||
280 | if (err < 0) { | ||
281 | sock->state = SS_UNCONNECTED; | ||
282 | sk->sk_state = TCP_CLOSE; | ||
283 | goto out; | ||
284 | } | ||
285 | |||
286 | err = -EINPROGRESS; | ||
287 | wait_connect: | ||
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 | |||
294 | err = -ERESTARTSYS; | ||
295 | timeo = wait_event_interruptible_timeout(*sk_sleep(sk), | ||
296 | sk->sk_state != TCP_CLOSE, | ||
297 | timeo); | ||
298 | |||
299 | lock_sock(sk); | ||
300 | if (timeo < 0) | ||
301 | goto out; /* -ERESTARTSYS */ | ||
302 | |||
303 | err = -ETIMEDOUT; | ||
304 | if (timeo == 0 && sk->sk_state != TCP_SYN_RECV) | ||
305 | goto out; | ||
306 | |||
307 | if (sk->sk_state != TCP_SYN_RECV) { | ||
308 | sock->state = SS_UNCONNECTED; | ||
309 | err = sock_error(sk); | ||
310 | if (!err) | ||
311 | err = -ECONNREFUSED; | ||
312 | goto out; | ||
313 | } | ||
314 | sock->state = SS_CONNECTED; | ||
315 | err = 0; | ||
316 | |||
317 | out: | ||
318 | release_sock(sk); | ||
319 | return err; | ||
320 | } | ||
321 | #endif | ||
322 | |||
228 | static int pn_socket_accept(struct socket *sock, struct socket *newsock, | 323 | static int pn_socket_accept(struct socket *sock, struct socket *newsock, |
229 | int flags) | 324 | int flags) |
230 | { | 325 | { |
@@ -393,7 +488,11 @@ const struct proto_ops phonet_stream_ops = { | |||
393 | .owner = THIS_MODULE, | 488 | .owner = THIS_MODULE, |
394 | .release = pn_socket_release, | 489 | .release = pn_socket_release, |
395 | .bind = pn_socket_bind, | 490 | .bind = pn_socket_bind, |
491 | #ifdef CONFIG_PHONET_PIPECTRLR | ||
492 | .connect = pn_socket_connect, | ||
493 | #else | ||
396 | .connect = sock_no_connect, | 494 | .connect = sock_no_connect, |
495 | #endif | ||
397 | .socketpair = sock_no_socketpair, | 496 | .socketpair = sock_no_socketpair, |
398 | .accept = pn_socket_accept, | 497 | .accept = pn_socket_accept, |
399 | .getname = pn_socket_getname, | 498 | .getname = pn_socket_getname, |