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
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
) {
62 int cor_socket_bind(struct socket
*sock
, struct sockaddr
*myaddr
,
65 struct connlistener
*listener
;
66 struct cor_sockaddr
*addr
= (struct cor_sockaddr
*) myaddr
;
71 if (sockaddr_len
< sizeof(struct cor_sockaddr
))
74 if (addr
->type
!= SOCKADDRTYPE_PORT
)
77 listener
= open_port(addr
->addr
.port
);
82 sock
->sk
= (struct sock
*) listener
;
87 int cor_socket_connect(struct socket
*sock
, struct sockaddr
*vaddr
,
88 int sockaddr_len
, int flags
)
90 struct conn
*conn_rcv
;
95 conn_rcv
= alloc_conn(GFP_KERNEL
);
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
;
109 static int cor_rdytoaccept(struct connlistener
*cl
)
112 mutex_lock(&(cl
->lock
));
113 rc
= (list_empty(&(cl
->conn_queue
)) == 0);
114 mutex_unlock(&(cl
->lock
));
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
;
131 mutex_lock(&(cl
->lock
));
133 if (unlikely(cl
->queue_maxlen
<= 0)) {
134 mutex_unlock(&(cl
->lock
));
138 while (list_empty(&(cl
->conn_queue
))) {
139 mutex_unlock(&(cl
->lock
));
140 if (wait_event_interruptible(cl
->wait
, cor_rdytoaccept(cl
))) {
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
);
155 mutex_unlock(&(cl
->lock
));
157 newsock
->ops
= &cor_proto_ops
;
158 newsock
->sk
= (struct sock
*) newconn
;
159 newsock
->state
= SS_CONNECTED
;
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
);
173 mutex_lock(&(cl
->lock
));
174 cl
->queue_maxlen
= len
;
175 mutex_unlock(&(cl
->lock
));
180 int cor_socket_shutdown(struct socket
*sock
, int flags
)
185 int cor_ioctl(struct socket
*sock
, unsigned int cmd
, unsigned long arg
)
190 static int sendmsg_maypush(struct conn
*rconn
)
193 mutex_lock(&(rconn
->rcv_lock
));
194 ret
= databuf_maypush(&(rconn
->buf
)) != 0;
195 mutex_unlock(&(rconn
->rcv_lock
));
199 int cor_sendmsg(struct kiocb
*iocb
, struct socket
*sock
, struct msghdr
*msg
,
204 struct conn
*rconn
= (struct conn
*) sock
->sk
;
206 int rc
= check_conn_state(rconn
);
208 int blocking
= (msg
->msg_flags
& MSG_DONTWAIT
) == 0;
214 mutex_lock(&(rconn
->rcv_lock
));
216 if (unlikely(rconn
->isreset
)) {
221 copied
= receive_userbuf(rconn
, msg
);
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))
230 copied
= -ERESTARTSYS
;
236 static int cor_readytoread(struct conn
*sconn
)
239 mutex_lock(&(sconn
->rcv_lock
));
240 rc
= (sconn
->buf
.read_remaining
!= 0);
241 mutex_unlock(&(sconn
->rcv_lock
));
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
;
252 int rc
= check_conn_state(rconn
);
254 int blocking
= (flags
& MSG_DONTWAIT
) == 0;
262 mutex_lock(&(sconn
->rcv_lock
));
264 if (unlikely(rconn
->isreset
)) {
269 copied
= databuf_pulluser(sconn
, msg
);
270 databuf_ackread(&(sconn
->buf
));
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)
280 copied
= -ERESTARTSYS
;
286 const struct proto_ops cor_proto_ops
= {
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
,
296 .sendmsg
= cor_sendmsg
,
297 .recvmsg
= cor_recvmsg
312 int cor_createsock(struct net
*net
, struct socket
*sock
, int protocol
)
315 return -EPROTONOSUPPORT
;
317 sock
->state
= SS_UNCONNECTED
;
318 sock
->ops
= &cor_proto_ops
;
323 static struct net_proto_family cor_net_proto_family
= {
325 .create
= cor_createsock
,
329 static int __init
cor_sock_init(void)
331 sock_register(&cor_net_proto_family
);
335 module_init(cor_sock_init
);
337 MODULE_LICENSE("GPL");