2 * Connection oriented routing
3 * Copyright (C) 2007-2010 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
22 #include <linux/net.h>
23 #include <asm/uaccess.h>
27 static int check_connlistener_state(struct connlistener
*cl
)
29 if (likely(cl
!= 0 && cl
->sockstate
== SOCKSTATE_LISTENER
))
35 static int check_conn_state(struct conn
*conn
)
37 if (likely(conn
!= 0 && conn
->sockstate
== SOCKSTATE_CONN
))
43 int cor_socket_release(struct socket
*sock
)
45 struct connlistener
*cl
= (struct connlistener
*) sock
->sk
;
46 struct conn
*rconn
= (struct conn
*) sock
->sk
;
51 if (cl
->sockstate
== SOCKSTATE_LISTENER
) {
53 } else if (rconn
->sockstate
== SOCKSTATE_CONN
) {
55 kref_put(&(rconn
->ref
), free_conn
);
63 int cor_socket_bind(struct socket
*sock
, struct sockaddr
*myaddr
,
66 struct connlistener
*listener
;
67 struct cor_sockaddr
*addr
= (struct cor_sockaddr
*) myaddr
;
69 if (unlikely(sock
->sk
!= 0))
72 if (sockaddr_len
< sizeof(struct cor_sockaddr
))
75 if (addr
->type
!= SOCKADDRTYPE_PORT
)
78 listener
= open_port(addr
->addr
.port
);
83 sock
->sk
= (struct sock
*) listener
;
88 int cor_socket_connect(struct socket
*sock
, struct sockaddr
*vaddr
,
89 int sockaddr_len
, int flags
)
93 if (unlikely(sock
->sk
!= 0))
96 rconn
= alloc_conn(GFP_KERNEL
);
98 kref_get(&(rconn
->ref
));
100 if (unlikely(rconn
== 0))
103 mutex_lock(&(rconn
->rcv_lock
));
104 mutex_lock(&(rconn
->reversedir
->rcv_lock
));
105 conn_init_sock_source(rconn
);
106 conn_init_sock_target(rconn
->reversedir
);
107 mutex_unlock(&(rconn
->reversedir
->rcv_lock
));
108 mutex_unlock(&(rconn
->rcv_lock
));
110 sock
->sk
= (struct sock
*) rconn
;
111 sock
->state
= SS_CONNECTED
;
116 static int cor_rdytoaccept(struct connlistener
*cl
)
119 mutex_lock(&(cl
->lock
));
120 rc
= (list_empty(&(cl
->conn_queue
)) == 0);
121 mutex_unlock(&(cl
->lock
));
125 const struct proto_ops cor_proto_ops
;
127 int cor_socket_accept(struct socket
*sock
, struct socket
*newsock
, int flags
)
129 struct connlistener
*cl
= (struct connlistener
*) sock
->sk
;
131 int rc
= check_connlistener_state(cl
);
133 struct conn
*newconn
;
138 mutex_lock(&(cl
->lock
));
140 if (unlikely(cl
->queue_maxlen
<= 0)) {
141 mutex_unlock(&(cl
->lock
));
145 while (list_empty(&(cl
->conn_queue
))) {
146 mutex_unlock(&(cl
->lock
));
147 if (wait_event_interruptible(cl
->wait
, cor_rdytoaccept(cl
))) {
150 mutex_lock(&(cl
->lock
));
153 newconn
= container_of(cl
->conn_queue
.next
, struct conn
,
154 source
.sock
.cl_list
);
156 BUG_ON(newconn
->sourcetype
!= SOURCE_SOCK
);
158 list_del(cl
->conn_queue
.next
);
162 mutex_unlock(&(cl
->lock
));
164 newsock
->ops
= &cor_proto_ops
;
165 newsock
->sk
= (struct sock
*) newconn
;
166 newsock
->state
= SS_CONNECTED
;
171 int cor_socket_listen(struct socket
*sock
, int len
)
173 struct connlistener
*cl
= (struct connlistener
*) sock
->sk
;
175 int rc
= check_connlistener_state(cl
);
180 mutex_lock(&(cl
->lock
));
181 cl
->queue_maxlen
= len
;
182 mutex_unlock(&(cl
->lock
));
187 int cor_socket_shutdown(struct socket
*sock
, int flags
)
192 int cor_ioctl(struct socket
*sock
, unsigned int cmd
, unsigned long arg
)
197 static int sendmsg_maypush(struct conn
*rconn
)
200 mutex_lock(&(rconn
->rcv_lock
));
201 ret
= (databuf_maypush(&(rconn
->buf
)) != 0) ||
202 unlikely(atomic_read(&(rconn
->isreset
)) != 0);
203 mutex_unlock(&(rconn
->rcv_lock
));
207 int cor_sendmsg(struct kiocb
*iocb
, struct socket
*sock
, struct msghdr
*msg
,
212 struct conn
*rconn
= (struct conn
*) sock
->sk
;
214 int rc
= check_conn_state(rconn
);
216 int blocking
= (msg
->msg_flags
& MSG_DONTWAIT
) == 0;
222 mutex_lock(&(rconn
->rcv_lock
));
224 if (unlikely(atomic_read(&(rconn
->isreset
)) != 0)) {
229 copied
= receive_userbuf(rconn
, msg
);
232 mutex_unlock(&(rconn
->rcv_lock
));
234 if (copied
== -EAGAIN
&& blocking
) {
235 if (wait_event_interruptible(rconn
->source
.sock
.wait
,
236 sendmsg_maypush(rconn
) == 0))
238 copied
= -ERESTARTSYS
;
244 static int cor_readytoread(struct conn
*sconn
)
247 mutex_lock(&(sconn
->rcv_lock
));
248 rc
= (sconn
->buf
.read_remaining
!= 0) ||
249 unlikely(atomic_read(&(sconn
->isreset
)) != 0);
250 mutex_unlock(&(sconn
->rcv_lock
));
254 int cor_recvmsg(struct kiocb
*iocb
, struct socket
*sock
, struct msghdr
*msg
,
255 size_t total_len
, int flags
)
257 struct conn
*rconn
= (struct conn
*) sock
->sk
;
258 struct conn
*sconn
= rconn
->reversedir
;
261 int rc
= check_conn_state(rconn
);
263 int blocking
= (flags
& MSG_DONTWAIT
) == 0;
271 mutex_lock(&(sconn
->rcv_lock
));
273 if (unlikely(atomic_read(&(rconn
->isreset
)) != 0)) {
278 copied
= databuf_pulluser(sconn
, msg
);
279 databuf_ackread(sconn
);
283 mutex_unlock(&(sconn
->rcv_lock
));
285 if (copied
== -EAGAIN
&& blocking
) {
286 if (wait_event_interruptible(sconn
->target
.sock
.wait
,
287 cor_readytoread(sconn
)) == 0)
289 copied
= -ERESTARTSYS
;
295 const struct proto_ops cor_proto_ops
= {
297 .owner
= THIS_MODULE
,
298 .release
= cor_socket_release
,
299 .bind
= cor_socket_bind
,
300 .connect
= cor_socket_connect
,
301 .accept
= cor_socket_accept
,
302 .listen
= cor_socket_listen
,
303 .shutdown
= cor_socket_shutdown
,
305 .sendmsg
= cor_sendmsg
,
306 .recvmsg
= cor_recvmsg
321 int cor_createsock(struct net
*net
, struct socket
*sock
, int protocol
)
323 if (unlikely(protocol
!= 0))
324 return -EPROTONOSUPPORT
;
326 sock
->state
= SS_UNCONNECTED
;
327 sock
->ops
= &cor_proto_ops
;
332 static struct net_proto_family cor_net_proto_family
= {
334 .create
= cor_createsock
,
338 static int __init
cor_sock_init(void)
340 sock_register(&cor_net_proto_family
);
344 module_init(cor_sock_init
);
346 MODULE_LICENSE("GPL");