[NET]: Round out in-kernel sockets API
authorSridhar Samudrala <sri@us.ibm.com>
Tue, 8 Aug 2006 03:57:31 +0000 (20:57 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 22 Sep 2006 21:54:05 +0000 (14:54 -0700)
This patch implements wrapper functions that provide a convenient way
to access the sockets API for in-kernel users like sunrpc, cifs &
ocfs2 etc and any future users.

Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/net.h
net/socket.c

index b20c53c744130384ae7ad28a9b8a6d1bdf5ff716..19da2c08d7b6b75a36946ff6a32c867077a961d5 100644 (file)
@@ -208,6 +208,25 @@ extern int              kernel_recvmsg(struct socket *sock, struct msghdr *msg,
                                    struct kvec *vec, size_t num,
                                    size_t len, int flags);
 
+extern int kernel_bind(struct socket *sock, struct sockaddr *addr,
+                      int addrlen);
+extern int kernel_listen(struct socket *sock, int backlog);
+extern int kernel_accept(struct socket *sock, struct socket **newsock,
+                        int flags);
+extern int kernel_connect(struct socket *sock, struct sockaddr *addr,
+                         int addrlen, int flags);
+extern int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
+                             int *addrlen);
+extern int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
+                             int *addrlen);
+extern int kernel_getsockopt(struct socket *sock, int level, int optname,
+                            char *optval, int *optlen);
+extern int kernel_setsockopt(struct socket *sock, int level, int optname,
+                            char *optval, int optlen);
+extern int kernel_sendpage(struct socket *sock, struct page *page, int offset,
+                          size_t size, int flags);
+extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
+
 #ifndef CONFIG_SMP
 #define SOCKOPS_WRAPPED(name) name
 #define SOCKOPS_WRAP(name, fam)
index 6756e57e1ff0b01f80234142f13ec0e8dfb0e88f..2eaebf934a1a5b303c64d9d3de89ca7f904dc59c 100644 (file)
@@ -2170,6 +2170,109 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd,
 }
 #endif
 
+int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
+{
+       return sock->ops->bind(sock, addr, addrlen);
+}
+
+int kernel_listen(struct socket *sock, int backlog)
+{
+       return sock->ops->listen(sock, backlog);
+}
+
+int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
+{
+       struct sock *sk = sock->sk;
+       int err;
+
+       err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol,
+                              newsock);
+       if (err < 0)
+               goto done;
+
+       err = sock->ops->accept(sock, *newsock, flags);
+       if (err < 0) {
+               sock_release(*newsock);
+               goto done;
+       }
+
+       (*newsock)->ops = sock->ops;
+
+done:
+       return err;
+}
+
+int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
+                   int flags)
+{
+       return sock->ops->connect(sock, addr, addrlen, flags);
+}
+
+int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
+                        int *addrlen)
+{
+       return sock->ops->getname(sock, addr, addrlen, 0);
+}
+
+int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
+                        int *addrlen)
+{
+       return sock->ops->getname(sock, addr, addrlen, 1);
+}
+
+int kernel_getsockopt(struct socket *sock, int level, int optname,
+                       char *optval, int *optlen)
+{
+       mm_segment_t oldfs = get_fs();
+       int err;
+
+       set_fs(KERNEL_DS);
+       if (level == SOL_SOCKET)
+               err = sock_getsockopt(sock, level, optname, optval, optlen);
+       else
+               err = sock->ops->getsockopt(sock, level, optname, optval,
+                                           optlen);
+       set_fs(oldfs);
+       return err;
+}
+
+int kernel_setsockopt(struct socket *sock, int level, int optname,
+                       char *optval, int optlen)
+{
+       mm_segment_t oldfs = get_fs();
+       int err;
+
+       set_fs(KERNEL_DS);
+       if (level == SOL_SOCKET)
+               err = sock_setsockopt(sock, level, optname, optval, optlen);
+       else
+               err = sock->ops->setsockopt(sock, level, optname, optval,
+                                           optlen);
+       set_fs(oldfs);
+       return err;
+}
+
+int kernel_sendpage(struct socket *sock, struct page *page, int offset,
+                   size_t size, int flags)
+{
+       if (sock->ops->sendpage)
+               return sock->ops->sendpage(sock, page, offset, size, flags);
+
+       return sock_no_sendpage(sock, page, offset, size, flags);
+}
+
+int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
+{
+       mm_segment_t oldfs = get_fs();
+       int err;
+
+       set_fs(KERNEL_DS);
+       err = sock->ops->ioctl(sock, cmd, arg);
+       set_fs(oldfs);
+
+       return err;
+}
+
 /* ABI emulation layers need these two */
 EXPORT_SYMBOL(move_addr_to_kernel);
 EXPORT_SYMBOL(move_addr_to_user);
@@ -2186,3 +2289,13 @@ EXPORT_SYMBOL(sock_wake_async);
 EXPORT_SYMBOL(sockfd_lookup);
 EXPORT_SYMBOL(kernel_sendmsg);
 EXPORT_SYMBOL(kernel_recvmsg);
+EXPORT_SYMBOL(kernel_bind);
+EXPORT_SYMBOL(kernel_listen);
+EXPORT_SYMBOL(kernel_accept);
+EXPORT_SYMBOL(kernel_connect);
+EXPORT_SYMBOL(kernel_getsockname);
+EXPORT_SYMBOL(kernel_getpeername);
+EXPORT_SYMBOL(kernel_getsockopt);
+EXPORT_SYMBOL(kernel_setsockopt);
+EXPORT_SYMBOL(kernel_sendpage);
+EXPORT_SYMBOL(kernel_sock_ioctl);