Replacing the kernelcall "socketcall" with a partly copy
from linux net/socket.c
This call ist not in x86_64, ia64 and some other. With
the patch the kernelcall is replaced.
An other way will be an export of the needed function
in net/socket.c...
If there is something wrong with my patch, please let
it me known, it's me first kernelmodule working ;-/
--
wbr
Robert Valentan
diff -r 2604abf98ede tools/vnet/vnet-module/varp_socket.c
--- a/tools/vnet/vnet-module/varp_socket.c Tue Mar 28 09:09:44 2006
+++ b/tools/vnet/vnet-module/varp_socket.c Tue Mar 28 17:10:53 2006
@@ -16,6 +16,9 @@
* 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
*
*/
+
+static int errno;
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/version.h>
@@ -36,7 +39,6 @@
/* Get macros needed to define system calls as functions in the kernel. */
#define __KERNEL_SYSCALLS__
-static int errno;
#include <linux/unistd.h>
#define MODULE_NAME "VARP"
@@ -75,110 +77,254 @@
* The parts we need anyway.
*/
-/* Define the socketcall() syscall.
- * Multiplexes all the socket-related calls.
- *
- * @param call socket call id
- * @param args arguments (upto 6)
- * @return call-dependent value
- */
-static inline _syscall2(int, socketcall,
- int, call,
- unsigned long *, args)
+/* the following code is copied from linux-kernel/net/socket.c
+ * As replacement of the __NR_socketcall, which exists not in x86_64 and
+ * same other systems.
+ * An alternate will be an export of the copied-functions in net/socket.c
+ */
+#define MAX_SOCK_ADDR 128
int socket(int family, int type, int protocol){
- unsigned long args[6];
-
- args[0] = (unsigned long)family;
- args[1] = (unsigned long)type;
- args[2] = (unsigned long)protocol;
- return socketcall(SYS_SOCKET, args);
+
+ int retval;
+ struct socket *sock;
+ retval = sock_create(family, type, protocol, &sock);
+ if (retval < 0)
+ goto out;
+
+ retval = sock_map_fd(sock);
+ if (retval < 0)
+ goto out_release;
+
+out:
+ /* It may be already another descriptor 8) Not kernel problem. */
+ return retval;
+
+out_release:
+ sock_release(sock);
+ return retval;
}
int bind(int fd, struct sockaddr *umyaddr, int addrlen){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)umyaddr;
- args[2] = (unsigned long)addrlen;
- return socketcall(SYS_BIND, args);
+
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ int err;
+
+ if((sock = sockfd_lookup(fd,&err))!=NULL)
+ {
+ if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
+ err = security_socket_bind(sock, (struct sockaddr
*)address, addrlen);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+ err = sock->ops->bind(sock, (struct sockaddr *)address,
addrlen);
+ }
+ sockfd_put(sock);
+ }
+ return err;
}
int connect(int fd, struct sockaddr *uservaddr, int addrlen){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)uservaddr;
- args[2] = (unsigned long)addrlen;
- return socketcall(SYS_CONNECT, args);
+
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ int err;
+
+ sock = sockfd_lookup(fd, &err);
+ if (!sock)
+ goto out;
+ err = move_addr_to_kernel(uservaddr, addrlen, address);
+ if (err < 0)
+ goto out_put;
+
+ err = security_socket_connect(sock, (struct sockaddr *)address,
addrlen);
+ if (err)
+ goto out_put;
+
+ err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
+ sock->file->f_flags);
+out_put:
+ sockfd_put(sock);
+out:
+ return err;
}
int sendto(int fd, void * buff, size_t len,
unsigned flags, struct sockaddr *addr,
int addr_len){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)buff;
- args[2] = (unsigned long)len;
- args[3] = (unsigned long)flags;
- args[4] = (unsigned long)addr;
- args[5] = (unsigned long)addr_len;
- return socketcall(SYS_SENDTO, args);
+
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ int err;
+ struct msghdr msg;
+ struct iovec iov;
+
+ sock = sockfd_lookup(fd, &err);
+ if (!sock)
+ goto out;
+ iov.iov_base=buff;
+ iov.iov_len=len;
+ msg.msg_name=NULL;
+ msg.msg_iov=&iov;
+ msg.msg_iovlen=1;
+ msg.msg_control=NULL;
+ msg.msg_controllen=0;
+ msg.msg_namelen=0;
+ if(addr)
+ {
+ err = move_addr_to_kernel(addr, addr_len, address);
+ if (err < 0)
+ goto out_put;
+ msg.msg_name=address;
+ msg.msg_namelen=addr_len;
+ }
+ if (sock->file->f_flags & O_NONBLOCK)
+ flags |= MSG_DONTWAIT;
+ msg.msg_flags = flags;
+ err = sock_sendmsg(sock, &msg, len);
+
+out_put:
+ sockfd_put(sock);
+out:
+ return err;
}
int recvfrom(int fd, void * ubuf, size_t size,
unsigned flags, struct sockaddr *addr,
int *addr_len){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)ubuf;
- args[2] = (unsigned long)size;
- args[3] = (unsigned long)flags;
- args[4] = (unsigned long)addr;
- args[5] = (unsigned long)addr_len;
- return socketcall(SYS_RECVFROM, args);
+
+ struct socket *sock;
+ struct iovec iov;
+ struct msghdr msg;
+ char address[MAX_SOCK_ADDR];
+ int err,err2;
+
+ sock = sockfd_lookup(fd, &err);
+ if (!sock)
+ goto out;
+
+ msg.msg_control=NULL;
+ msg.msg_controllen=0;
+ msg.msg_iovlen=1;
+ msg.msg_iov=&iov;
+ iov.iov_len=size;
+ iov.iov_base=ubuf;
+ msg.msg_name=address;
+ msg.msg_namelen=MAX_SOCK_ADDR;
+ if (sock->file->f_flags & O_NONBLOCK)
+ flags |= MSG_DONTWAIT;
+ err=sock_recvmsg(sock, &msg, size, flags);
+
+ if(err >= 0 && addr != NULL)
+ {
+ err2=move_addr_to_user(address, msg.msg_namelen, addr,
addr_len);
+ if(err2<0)
+ err=err2;
+ }
+ sockfd_put(sock);
+out:
+ return err;
}
int setsockopt(int fd, int level, int optname, void *optval, int optlen){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)level;
- args[2] = (unsigned long)optname;
- args[3] = (unsigned long)optval;
- args[4] = (unsigned long)optlen;
- return socketcall(SYS_SETSOCKOPT, args);
-}
-
+
+ int err;
+ struct socket *sock;
+
+ if (optlen < 0)
+ return -EINVAL;
+
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ err = security_socket_setsockopt(sock,level,optname);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
+ if (level == SOL_SOCKET)
+ err=sock_setsockopt(sock,level,optname,optval,optlen);
+ else
+ err=sock->ops->setsockopt(sock, level, optname, optval,
optlen);
+ sockfd_put(sock);
+ }
+ return err;
+}
+
+/* not possible, because sock_getsockopt is not exported ...
int getsockopt(int fd, int level, int optname, void *optval, int *optlen){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)level;
- args[2] = (unsigned long)optname;
- args[3] = (unsigned long)optval;
- args[4] = (unsigned long)optlen;
- return socketcall(SYS_GETSOCKOPT, args);
-}
+
+ int err;
+ struct socket *sock;
+
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ err = security_socket_getsockopt(sock, level, optname);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
+ if (level == SOL_SOCKET)
+ err=sock_getsockopt(sock,level,optname,optval,optlen);
+ else
+ err=sock->ops->getsockopt(sock, level, optname, optval,
optlen);
+ sockfd_put(sock);
+ }
+ return err;
+}
+*/
int shutdown(int fd, int how){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)how;
- return socketcall(SYS_SHUTDOWN, args);
+
+ int err;
+ struct socket *sock;
+
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ err = security_socket_shutdown(sock, how);
+ if (err) {
+ sockfd_put(sock);
+ return err;
+ }
+
+ err=sock->ops->shutdown(sock, how);
+ sockfd_put(sock);
+ }
+ return err;
}
int getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len){
- unsigned long args[6];
-
- args[0] = (unsigned long)fd;
- args[1] = (unsigned long)usockaddr;
- args[2] = (unsigned long)usockaddr_len;
- return socketcall(SYS_GETSOCKNAME, args);
-}
+
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ int len, err;
+
+ sock = sockfd_lookup(fd, &err);
+ if (!sock)
+ goto out;
+
+ err = security_socket_getsockname(sock);
+ if (err)
+ goto out_put;
+
+ err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
+ if (err)
+ goto out_put;
+ err = move_addr_to_user(address, len, usockaddr, usockaddr_len);
+
+out_put:
+ sockfd_put(sock);
+out:
+ return err;
+}
+
+/**
+ * End of copy from net/socket.c
+ */
+
/*============================================================================*/
/** Socket flags. */
@@ -577,7 +723,7 @@
int err = 0;
mm_segment_t oldfs;
- dprintf("> mcaddr=%u.%u.%u.%u port=%u\n", NIPQUAD(mcaddr), ntohs(port));
+ iprintf("> mcaddr=%u.%u.%u.%u port=%u\n", NIPQUAD(mcaddr), ntohs(port));
oldfs = change_fs(KERNEL_DS);
err = varp_mcast_open(mcaddr, port, &varp_mcast_sock);
if(err < 0 ) goto exit;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|