aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Denis-Courmont <remi.denis-courmont@nokia.com>2008-10-05 14:14:48 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-05 14:14:48 -0400
commit9995a32b4d14dcda2f8df58030526bee91114c16 (patch)
treebca23fcdea1cde4160dd5e4a07a19c1689cd5348
parent25532824fb727744a302edb25c6a6ac10b82cb63 (diff)
Phonet: connected sockets glue
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/phonet/pep.h43
-rw-r--r--net/phonet/socket.c97
2 files changed, 140 insertions, 0 deletions
diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
new file mode 100644
index 000000000000..b2f8c54c5333
--- /dev/null
+++ b/include/net/phonet/pep.h
@@ -0,0 +1,43 @@
1/*
2 * File: pep.h
3 *
4 * Phonet Pipe End Point sockets definitions
5 *
6 * Copyright (C) 2008 Nokia Corporation.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23#ifndef NET_PHONET_PEP_H
24#define NET_PHONET_PEP_H
25
26struct pep_sock {
27 struct pn_sock pn_sk;
28
29 /* Listening socket stuff: */
30 struct hlist_head ackq;
31
32 /* Connected socket stuff: */
33 u8 tx_credits;
34};
35
36static inline struct pep_sock *pep_sk(struct sock *sk)
37{
38 return (struct pep_sock *)sk;
39}
40
41extern const struct proto_ops phonet_stream_ops;
42
43#endif
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index dfd4061646db..cea1136cbe46 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -25,11 +25,13 @@
25 25
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/net.h> 27#include <linux/net.h>
28#include <linux/poll.h>
28#include <net/sock.h> 29#include <net/sock.h>
29#include <net/tcp_states.h> 30#include <net/tcp_states.h>
30 31
31#include <linux/phonet.h> 32#include <linux/phonet.h>
32#include <net/phonet/phonet.h> 33#include <net/phonet/phonet.h>
34#include <net/phonet/pep.h>
33#include <net/phonet/pn_dev.h> 35#include <net/phonet/pn_dev.h>
34 36
35static int pn_socket_release(struct socket *sock) 37static int pn_socket_release(struct socket *sock)
@@ -166,6 +168,24 @@ static int pn_socket_autobind(struct socket *sock)
166 return 0; /* socket was already bound */ 168 return 0; /* socket was already bound */
167} 169}
168 170
171static int pn_socket_accept(struct socket *sock, struct socket *newsock,
172 int flags)
173{
174 struct sock *sk = sock->sk;
175 struct sock *newsk;
176 int err;
177
178 newsk = sk->sk_prot->accept(sk, flags, &err);
179 if (!newsk)
180 return err;
181
182 lock_sock(newsk);
183 sock_graft(newsk, newsock);
184 newsock->state = SS_CONNECTED;
185 release_sock(newsk);
186 return 0;
187}
188
169static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, 189static int pn_socket_getname(struct socket *sock, struct sockaddr *addr,
170 int *sockaddr_len, int peer) 190 int *sockaddr_len, int peer)
171{ 191{
@@ -182,6 +202,33 @@ static int pn_socket_getname(struct socket *sock, struct sockaddr *addr,
182 return 0; 202 return 0;
183} 203}
184 204
205static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
206 poll_table *wait)
207{
208 struct sock *sk = sock->sk;
209 struct pep_sock *pn = pep_sk(sk);
210 unsigned int mask = 0;
211
212 poll_wait(file, &sock->wait, wait);
213
214 switch (sk->sk_state) {
215 case TCP_LISTEN:
216 return hlist_empty(&pn->ackq) ? 0 : POLLIN;
217 case TCP_CLOSE:
218 return POLLERR;
219 }
220
221 if (!skb_queue_empty(&sk->sk_receive_queue))
222 mask |= POLLIN | POLLRDNORM;
223 else if (sk->sk_state == TCP_CLOSE_WAIT)
224 return POLLHUP;
225
226 if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits)
227 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
228
229 return mask;
230}
231
185static int pn_socket_ioctl(struct socket *sock, unsigned int cmd, 232static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,
186 unsigned long arg) 233 unsigned long arg)
187{ 234{
@@ -220,6 +267,30 @@ static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,
220 return sk->sk_prot->ioctl(sk, cmd, arg); 267 return sk->sk_prot->ioctl(sk, cmd, arg);
221} 268}
222 269
270static int pn_socket_listen(struct socket *sock, int backlog)
271{
272 struct sock *sk = sock->sk;
273 int err = 0;
274
275 if (sock->state != SS_UNCONNECTED)
276 return -EINVAL;
277 if (pn_socket_autobind(sock))
278 return -ENOBUFS;
279
280 lock_sock(sk);
281 if (sk->sk_state != TCP_CLOSE) {
282 err = -EINVAL;
283 goto out;
284 }
285
286 sk->sk_state = TCP_LISTEN;
287 sk->sk_ack_backlog = 0;
288 sk->sk_max_ack_backlog = backlog;
289out:
290 release_sock(sk);
291 return err;
292}
293
223static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock, 294static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock,
224 struct msghdr *m, size_t total_len) 295 struct msghdr *m, size_t total_len)
225{ 296{
@@ -256,6 +327,32 @@ const struct proto_ops phonet_dgram_ops = {
256 .sendpage = sock_no_sendpage, 327 .sendpage = sock_no_sendpage,
257}; 328};
258 329
330const struct proto_ops phonet_stream_ops = {
331 .family = AF_PHONET,
332 .owner = THIS_MODULE,
333 .release = pn_socket_release,
334 .bind = pn_socket_bind,
335 .connect = sock_no_connect,
336 .socketpair = sock_no_socketpair,
337 .accept = pn_socket_accept,
338 .getname = pn_socket_getname,
339 .poll = pn_socket_poll,
340 .ioctl = pn_socket_ioctl,
341 .listen = pn_socket_listen,
342 .shutdown = sock_no_shutdown,
343 .setsockopt = sock_no_setsockopt,
344 .getsockopt = sock_no_getsockopt,
345#ifdef CONFIG_COMPAT
346 .compat_setsockopt = sock_no_setsockopt,
347 .compat_getsockopt = compat_sock_no_getsockopt,
348#endif
349 .sendmsg = pn_socket_sendmsg,
350 .recvmsg = sock_common_recvmsg,
351 .mmap = sock_no_mmap,
352 .sendpage = sock_no_sendpage,
353};
354EXPORT_SYMBOL(phonet_stream_ops);
355
259static DEFINE_MUTEX(port_mutex); 356static DEFINE_MUTEX(port_mutex);
260 357
261/* allocate port for a socket */ 358/* allocate port for a socket */