neighbor free after disconnect
[cor_2_6_31.git] / net / cor / sock.c
blobf308247275bb69b3adf9dd8a4075a4b1cb13e0f0
1 /*
2 * Connection oriented routing
3 * Copyright (C) 2007-2008 Michael Blizek
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 #include <net/sock.h>
22 #include <linux/net.h>
23 #include <asm/uaccess.h>
25 #include "cor.h"
27 static int check_connlistener_state(struct connlistener *cl)
29 if (likely(cl != 0 && cl->sockstate == SOCKSTATE_LISTENER))
30 return 0;
32 return 1;
35 static int check_conn_state(struct conn *conn)
37 if (likely(conn != 0 && conn->sockstate == SOCKSTATE_CONN))
38 return 0;
40 return 1;
43 int cor_socket_release(struct socket *sock)
45 struct connlistener *cl = (struct connlistener *) sock->sk;
46 struct conn *rconn = (struct conn *) sock->sk;
48 if (sock->sk == 0)
49 return 0;
51 if (cl->sockstate == SOCKSTATE_LISTENER) {
52 close_port(cl);
53 } else if (rconn->sockstate == SOCKSTATE_CONN) {
54 reset_conn(rconn);
55 } else {
56 BUG();
59 return 0;
62 int cor_socket_bind(struct socket *sock, struct sockaddr *myaddr,
63 int sockaddr_len)
65 struct connlistener *listener;
66 struct cor_sockaddr *addr = (struct cor_sockaddr *) myaddr;
68 if (sock->sk != 0)
69 return -EINVAL;
71 if (sockaddr_len < sizeof(struct cor_sockaddr))
72 return -EINVAL;
74 if (addr->type != SOCKADDRTYPE_PORT)
75 return -EINVAL;
77 listener = open_port(addr->addr.port);
79 if (listener == 0)
80 return -EADDRINUSE;
82 sock->sk = (struct sock *) listener;
84 return 0;
87 int cor_socket_connect(struct socket *sock, struct sockaddr *vaddr,
88 int sockaddr_len, int flags)
90 struct conn *conn_rcv;
92 if (sock->sk != 0)
93 return -EISCONN;
95 conn_rcv = alloc_conn(GFP_KERNEL);
97 if (0 == conn_rcv)
98 return -ENOMEM;
100 conn_init_sock_source(conn_rcv);
101 conn_init_sock_target(conn_rcv->reversedir);
103 sock->sk = (struct sock *) conn_rcv;
104 sock->state = SS_CONNECTED;
106 return 0;
109 static int cor_rdytoaccept(struct connlistener *cl)
111 int rc;
112 mutex_lock(&(cl->lock));
113 rc = (list_empty(&(cl->conn_queue)) == 0);
114 mutex_unlock(&(cl->lock));
115 return rc;
118 const struct proto_ops cor_proto_ops;
120 int cor_socket_accept(struct socket *sock, struct socket *newsock, int flags)
122 struct connlistener *cl = (struct connlistener *) sock->sk;
124 int rc = check_connlistener_state(cl);
126 struct conn *newconn;
128 if (unlikely(rc))
129 return -EINVAL;
131 mutex_lock(&(cl->lock));
133 if (unlikely(cl->queue_maxlen <= 0)) {
134 mutex_unlock(&(cl->lock));
135 return -EINVAL;
138 while (list_empty(&(cl->conn_queue))) {
139 mutex_unlock(&(cl->lock));
140 if (wait_event_interruptible(cl->wait, cor_rdytoaccept(cl))) {
141 return -ERESTARTSYS;
143 mutex_lock(&(cl->lock));
146 newconn = container_of(cl->conn_queue.next, struct conn,
147 source.sock.cl_list);
149 BUG_ON(newconn->sourcetype != SOURCE_SOCK);
151 list_del(cl->conn_queue.next);
153 cl->queue_len--;
155 mutex_unlock(&(cl->lock));
157 newsock->ops = &cor_proto_ops;
158 newsock->sk = (struct sock *) newconn;
159 newsock->state = SS_CONNECTED;
161 return 0;
164 int cor_socket_listen(struct socket *sock, int len)
166 struct connlistener *cl = (struct connlistener *) sock->sk;
168 int rc = check_connlistener_state(cl);
170 if (unlikely(rc))
171 return -EOPNOTSUPP;
173 mutex_lock(&(cl->lock));
174 cl->queue_maxlen = len;
175 mutex_unlock(&(cl->lock));
177 return 0;
180 int cor_socket_shutdown(struct socket *sock, int flags)
182 return -ENOTSUPP;
185 int cor_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
187 return -ENOIOCTLCMD;
190 static int sendmsg_maypush(struct conn *rconn)
192 int ret;
193 mutex_lock(&(rconn->rcv_lock));
194 ret = databuf_maypush(&(rconn->buf)) != 0;
195 mutex_unlock(&(rconn->rcv_lock));
196 return ret;
199 int cor_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
200 size_t total_len)
202 int copied = 0;
204 struct conn *rconn = (struct conn *) sock->sk;
206 int rc = check_conn_state(rconn);
208 int blocking = (msg->msg_flags & MSG_DONTWAIT) == 0;
210 if (unlikely(rc))
211 return -EBADF;
213 recv:
214 mutex_lock(&(rconn->rcv_lock));
216 if (unlikely(rconn->isreset)) {
217 copied = -EPIPE;
218 goto out;
221 copied = receive_userbuf(rconn, msg);
223 out:
224 mutex_unlock(&(rconn->rcv_lock));
226 if (copied == -EAGAIN && blocking) {
227 if (wait_event_interruptible(rconn->source.sock.wait,
228 sendmsg_maypush(rconn) == 0))
229 goto recv;
230 copied = -ERESTARTSYS;
233 return copied;
236 static int cor_readytoread(struct conn *sconn)
238 int rc = 0;
239 mutex_lock(&(sconn->rcv_lock));
240 rc = (sconn->buf.read_remaining != 0);
241 mutex_unlock(&(sconn->rcv_lock));
242 return rc;
245 int cor_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
246 size_t total_len, int flags)
248 struct conn *rconn = (struct conn *) sock->sk;
249 struct conn *sconn = rconn->reversedir;
250 size_t copied = 0;
252 int rc = check_conn_state(rconn);
254 int blocking = (flags & MSG_DONTWAIT) == 0;
256 if (unlikely(rc))
257 return -EBADF;
259 BUG_ON(sconn == 0);
261 recv:
262 mutex_lock(&(sconn->rcv_lock));
264 if (unlikely(rconn->isreset)) {
265 copied = -EPIPE;
266 goto out;
269 copied = databuf_pulluser(sconn, msg);
270 databuf_ackread(&(sconn->buf));
271 wake_sender(sconn);
273 out:
274 mutex_unlock(&(sconn->rcv_lock));
276 if (copied == -EAGAIN && blocking) {
277 if (wait_event_interruptible(sconn->target.sock.wait,
278 cor_readytoread(sconn)) == 0)
279 goto recv;
280 copied = -ERESTARTSYS;
283 return copied;
286 const struct proto_ops cor_proto_ops = {
287 .family = PF_COR,
288 .owner = THIS_MODULE,
289 .release = cor_socket_release,
290 .bind = cor_socket_bind,
291 .connect = cor_socket_connect,
292 .accept = cor_socket_accept,
293 .listen = cor_socket_listen,
294 .shutdown = cor_socket_shutdown,
295 .ioctl = cor_ioctl,
296 .sendmsg = cor_sendmsg,
297 .recvmsg = cor_recvmsg
299 /*socketpair
300 getname
301 poll
302 compat_ioctl
303 setsockopt
304 getsockopt
305 compat_setsockopt
306 compat_getsockopt
307 mmap
308 sendpage
309 splice_read*/
312 int cor_createsock(struct net *net, struct socket *sock, int protocol)
314 if (0 != protocol)
315 return -EPROTONOSUPPORT;
317 sock->state = SS_UNCONNECTED;
318 sock->ops = &cor_proto_ops;
320 return 0;
323 static struct net_proto_family cor_net_proto_family = {
324 .family = PF_COR,
325 .create = cor_createsock,
326 .owner = THIS_MODULE
329 static int __init cor_sock_init(void)
331 sock_register(&cor_net_proto_family);
332 return 0;
335 module_init(cor_sock_init);
337 MODULE_LICENSE("GPL");