From: Răzvan Crainea Date: Sun, 27 May 2012 15:22:45 +0000 (+0300) Subject: module: added support for multiple USERSPACE receivers X-Git-Url: http://p2p-next.cs.pub.ro/gitweb/?a=commitdiff_plain;h=2d6f09bf6e183a2a889d52af3c0acc48c5998043;p=p2p-kernel-protocol.git module: added support for multiple USERSPACE receivers test: added testing program --- diff --git a/module/Kbuild b/module/Kbuild index 1934d9d..1b5fb8e 100644 --- a/module/Kbuild +++ b/module/Kbuild @@ -1,3 +1,4 @@ EXTRA_CFLAGS = -Wall -g -obj-m = p2psp.o +obj-m = af_p2pkp.o +af_p2pkp-y = p2pkp.o p2pkp_sock.o p2pkp_file.o p2pkp_net.o diff --git a/module/p2pkp.c b/module/p2pkp.c new file mode 100644 index 0000000..5561991 --- /dev/null +++ b/module/p2pkp.c @@ -0,0 +1,75 @@ +/* + * Peer to Peer Kernel Protocol + * + * Răzvan Crainea + * Tudor Cazangiu + */ + +#include +#include +#include + +#include "p2pkp_sock.h" +#include "p2pkp_debug.h" + +MODULE_DESCRIPTION("P2P Kernel Protocol"); +MODULE_AUTHOR("Razvan Crainea and Tudor Cazangiu"); +MODULE_LICENSE("GPL"); + +int __init p2pkp_sock_init(void) +{ + //int bytes_read; + //struct file *file = NULL; + +#if 0 + /* address to bind on */ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(P2PKP_LOCAL_PORT), + .sin_addr = { htonl(INADDR_LOOPBACK) } + }; + int addrlen = sizeof(addr); +#endif + + if (p2pkp_register_protocol() < 0) { + ERROR("error while registering socket operations"); + return -1; + } + return 0; + +#if 0 + /* bind socket to loopback on port P2PKP_LOCAL_PORT */ + err = sock->ops->bind(sock, (struct sockaddr *) &addr, addrlen); + if (err < 0) { + ERROR("can't bind socket\n"); + goto out_release; + } + + /* send first message */ + err = p2pkp_msgsend(sock, P2PKP_REMOTE_PORT1); + if (err < 0) { + ERROR("can't send first message\n"); + goto out_release; + } + + /* send second message */ + err = p2pkp_msgsend(sock, P2PKP_REMOTE_PORT1); + if (err < 0) { + ERROR("can't send second message\n"); + goto out_release; + } + +out_release: + /* cleanup socket */ + sock_release(sock); +#endif +} + +void __exit p2pkp_sock_exit(void) +{ + /* cleanup socket */ + p2pkp_unregister_protocol(); +} + +module_init(p2pkp_sock_init); +module_exit(p2pkp_sock_exit); diff --git a/module/p2pkp.h b/module/p2pkp.h new file mode 100644 index 0000000..f18d258 --- /dev/null +++ b/module/p2pkp.h @@ -0,0 +1,7 @@ +#ifndef _P2PKP_H_ +#define _P2PKP_H_ + +#define AF_P2PKP 19 +#define PF_P2PKP AF_P2PKP + +#endif /* _P2PKP_H_ */ diff --git a/module/p2pkp_debug.h b/module/p2pkp_debug.h new file mode 100644 index 0000000..2b8e944 --- /dev/null +++ b/module/p2pkp_debug.h @@ -0,0 +1,37 @@ +#ifndef _P2PKP_DEBUG_H_ +#define _P2PKP_DEBUG_H_ + +//#include "linux/kernel.h" + +#ifndef P2PKP_DEBUG + /* uncomment to turn debugging off */ + #define P2PKP_DEBUG yes +#endif + +#ifdef P2PKP_DEBUG +#define DEBUG(format, args...) \ + do { \ + printk(KERN_DEBUG "[%s:%d] " format "\n", __func__, __LINE__, ## args); \ + } while (0) +#else +#define LOG(s) \ + do {} while (0) +#endif + +/* p2pkp error func */ +#define ERROR(format, args...) \ + do { \ + printk(KERN_ERR "[%s:%d] " format "\n", __func__, __LINE__, ## args); \ + } while (0) + +#define print_sock_address(addr) \ + do { \ + printk(LOG_DEBUG "connection established to " \ + NIPQUAD_FMT ":%d\n", \ + NIPQUAD(addr.sin_addr.s_addr), \ + ntohs(addr.sin_port)); \ + } while (0) + + +#endif /* _P2PKP_DEBUG_H_ */ + diff --git a/module/p2pkp_file.c b/module/p2pkp_file.c new file mode 100644 index 0000000..48dc67c --- /dev/null +++ b/module/p2pkp_file.c @@ -0,0 +1,54 @@ +#include +#include + +#include "p2pkp_file.h" +#include "p2pkp_debug.h" + +struct file* p2pkp_open_file_read(const char *filename) +{ + struct file * file; + file = filp_open(filename, O_RDONLY, 0); + return IS_ERR_OR_NULL(file) ? NULL : file; +} + +void p2pkp_close_file(struct file *file) +{ + filp_close(file,NULL); +} + +int p2pkp_read_from_file(struct file *file, char *buffer, int len) +{ + // Create variables + int read_bytes, offset; + mm_segment_t fs; + + // To see in /var/log/messages that the module is operating + if(file == NULL) { + ERROR("filp_open error!!"); + return -EINVAL; + } + DEBUG("Changinig segment descriptor"); + // Get current segment descriptor + fs = get_fs(); + // Set segment descriptor associated to kernel space + set_fs(get_ds()); + DEBUG("Changed segment descriptor - buffer is %p", buffer); + + offset = 0; + do { + read_bytes = file->f_op->read(file, buffer + offset, len, &file->f_pos); + if (read_bytes > 0) { + offset += read_bytes; + len -= read_bytes; + } + } while (/*(read_bytes < 0 && errno == EINVAL)||*/(read_bytes > 0 && len > 0)); + + set_fs(fs); + + if (read_bytes < 0) { + ERROR("error while reading from file!"); + } + + return offset; +} + diff --git a/module/p2pkp_file.h b/module/p2pkp_file.h new file mode 100644 index 0000000..f98e32f --- /dev/null +++ b/module/p2pkp_file.h @@ -0,0 +1,9 @@ +#ifndef _P2PKP_FILE_H_ +#define _P2PKP_FILE_H_ + + +struct file* p2pkp_open_file_read(const char *filename); +void p2pkp_close_file(struct file *file); +int p2pkp_read_from_file(struct file *file, char *buffer, int len); + +#endif /* _P2PKP_FILE_H_ */ diff --git a/module/p2pkp_net.c b/module/p2pkp_net.c new file mode 100644 index 0000000..c178a71 --- /dev/null +++ b/module/p2pkp_net.c @@ -0,0 +1,45 @@ +#include "p2pkp_net.h" +#include "p2pkp_debug.h" + +#include +#include + + +/* send datagram */ +int p2pkp_msgsend(struct socket *s, struct sockaddr_in *sin, char *buffer, int len) +{ + /* message */ + struct msghdr msg; + struct iovec iov; + + /* build message */ + iov.iov_base = buffer; + iov.iov_len = len; + msg.msg_name = sin; + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + /* send the message down the socket */ + return kernel_sendmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len); +} + + +int p2pkp_create_udp_sock(struct socket **sock) +{ + if (!sock) { + ERROR("socket memory not specified"); + return -EINVAL; + } + + /* create UDP socket */ + return sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, sock); +} + +void p2pkp_destroy_udp_sock(struct socket *sock) +{ + sock_release(sock); +} diff --git a/module/p2pkp_net.h b/module/p2pkp_net.h new file mode 100644 index 0000000..dd43124 --- /dev/null +++ b/module/p2pkp_net.h @@ -0,0 +1,12 @@ +#ifndef _P2PKP_NET_H_ +#define _P2PKP_NET_H_ + +#include +#include + + +int p2pkp_create_udp_sock(struct socket **sock); +void p2pkp_destroy_udp_sock(struct socket *sock); +int p2pkp_msgsend(struct socket *s, struct sockaddr_in *sin, char *buffer, int len); + +#endif /* _P2PKP_NET_H_ */ diff --git a/module/p2pkp_sock.c b/module/p2pkp_sock.c new file mode 100644 index 0000000..d72fdb3 --- /dev/null +++ b/module/p2pkp_sock.c @@ -0,0 +1,322 @@ +#include +#include +#include + +#include "p2pkp.h" +#include "p2pkp_net.h" +#include "p2pkp_sock.h" +#include "p2pkp_debug.h" +#include "p2pkp_file.h" + + +static int p2pkp_release(struct socket *sock); +static int p2pkp_bind(struct socket *sock, struct sockaddr *myaddr, + int sockaddr_len); +static int p2pkp_connect(struct socket *sock, struct sockaddr *vaddr, + int sockaddr_len, int flags); +static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len); +static int p2pkp_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, int flags); + +/* creates a socket */ +static int p2pkp_create(struct net *net, struct socket *sock, int protocol, + int kern); + +/* protocol */ +static struct proto p2pkp_proto = { + .name = P2PKP_PROTO_NAME, + .owner = THIS_MODULE, + .obj_size = sizeof(struct p2pkp_sock), +}; + +/* protocol operations */ +static const struct proto_ops p2pkp_ops = { + .family = PF_P2PKP, + .owner = THIS_MODULE, + .release = p2pkp_release, + .bind = p2pkp_bind, + .connect = p2pkp_connect, + .sendmsg = p2pkp_sendmsg, + .recvmsg = p2pkp_recvmsg, + + /* unimplemented */ + .poll = datagram_poll, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = sock_no_getname, + .ioctl = sock_no_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; + + +/* family socket */ +static const struct net_proto_family p2pkp_family_ops = { + .family = PF_P2PKP, + .create = p2pkp_create, + .owner = THIS_MODULE, +}; + + + +int p2pkp_register_protocol(void) +{ + int err; + + err = sock_register(&p2pkp_family_ops); + if (err) { + ERROR("cannot register operations"); + goto exit; + } + + err = proto_register(&p2pkp_proto, 0); + if (err) { + ERROR("cannot register proto"); + goto sock_unreg; + } + DEBUG("Successfully registered socket operations"); + + return 0; + +sock_unreg: + sock_unregister(PF_P2PKP); +exit: + return err; + +} + +void p2pkp_unregister_protocol(void) +{ + DEBUG("Unregistering protocol"); + proto_unregister(&p2pkp_proto); + sock_unregister(PF_P2PKP); + DEBUG("Successfully UNregistered socket operations"); +} + + +static int p2pkp_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + struct p2pkp_sock *ps = sock2p2pkp(sk); + + if (!sk) + return 0; + + lock_sock(sk); + sock_orphan(sk); + sk->sk_shutdown = SEND_SHUTDOWN; + + skb_queue_purge(&sk->sk_receive_queue); + skb_queue_purge(&sk->sk_write_queue); + skb_queue_purge(&sk->sk_error_queue); + + /* TODO: some statistics, don't know if really + * needed */ + //sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + + /* TODO do whatever is needed with ps */ + + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_state_change(sk); + + release_sock(sk); + + sock_set_flag(sk, SOCK_DEAD); + sock->sk = NULL; + + p2pkp_destroy_udp_sock(ps->net_sock); + + sock_put(sk); + DEBUG("Released the socket"); + return 0; +} + +static int p2pkp_bind(struct socket *sock, struct sockaddr *myaddr, + int sockaddr_len){return 0;} + + +static int p2pkp_connect(struct socket *sock, struct sockaddr *vaddr, + int sockaddr_len, int flags) +{ + struct sock *sk = sock->sk; + struct p2pkp_sock *ps = sock2p2pkp(sk); + struct p2pkp_conn_info *pconn; + + if (!sk || !vaddr || sockaddr_len != sizeof(struct sockaddr_in) || + vaddr->sa_family != AF_INET) { + ERROR("invalid socket parameters"); + return -EINVAL; + } + + pconn = kmalloc(sizeof(struct p2pkp_conn_info), GFP_KERNEL); + if (!pconn) { + ERROR("no more memory for new list element"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&pconn->list); + memcpy(&pconn->sin, vaddr, sockaddr_len); + + lock_sock(sk); + + /* TODO spinlock required? */ + list_add(&pconn->list, &ps->conn_list); + + sock->state = SS_CONNECTED; + release_sock(sk); + + DEBUG("Connected socket to a peer"); + + return 0; +} + +static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + int err = -ENXIO; + int f_index, bytes_read; + struct sock *sk = sock->sk; + struct p2pkp_sock *ps = sock2p2pkp(sk); + struct sockaddr_in *sin = (struct sockaddr_in *)m->msg_name; + struct file * file; + char *file_name; + struct list_head *pos; + struct p2pkp_conn_info *conn; + + if (!sk || !sock || + (sin && sizeof(struct sockaddr_in) != m->msg_namelen)) { + ERROR("invalid socket parameters"); + return -EINVAL; + } + + if (sin && ((err = p2pkp_connect(sock, (struct sockaddr *)sin, + sizeof(struct sockaddr_in), 0)) < 0)) { + ERROR("cannot connect to socket"); + return err; + } + + lock_sock(sk); + if (!(sock->state & SS_CONNECTED)) { + ERROR("unconnected socket"); + err = -ECONNREFUSED; + goto release; + } + release_sock(sk); + + /* check if the file exists */ + for (f_index = 0; f_index < m->msg_iovlen; f_index++) { + file_name = (char *)m->msg_iov[f_index].iov_base; + file = p2pkp_open_file_read(file_name); + if (!file) { + ERROR("cannot open file %s\n", file_name); + continue; + } + DEBUG("opened file %s", file_name); + for (;;) { + bytes_read = p2pkp_read_from_file(file, ps->buffer, ps->buffer_len); + DEBUG("read %d bytes from file", bytes_read); + if (bytes_read < 0) { + ERROR("cannot read from file"); + goto out_close; + } + if (bytes_read == 0) + goto out_close; + + lock_sock(sk); + /* iterate through all the connections to send the data */ + list_for_each(pos, &ps->conn_list) { + + conn = list_entry(pos, struct p2pkp_conn_info, list); + err = p2pkp_msgsend(ps->net_sock, + &conn->sin, ps->buffer, ps->buffer_len); + if (err < 0) { + ERROR("can't send first message"); + goto out_conn; + } + } +out_conn: + release_sock(sk); + } + +out_close: + + p2pkp_close_file(file); + } + + + DEBUG("Sending completed successfully"); + err = 0; +release: + release_sock(sk); + return err; +} + + +static int p2pkp_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, int flags){return 0;} + + +static int p2pkp_create(struct net *net, struct socket *sock, int protocol, + int kern) +{ + struct sock *sk = NULL; + struct p2pkp_sock *ps; + int err = -ESOCKTNOSUPPORT; + + DEBUG("Creating new P2PKP socket"); + if (sock->type != SOCK_DGRAM) { + ERROR("P2PKP supports only SOCK_DGRAM sockets"); + goto error; + } + if (protocol) { + ERROR("protocol %x not suported - currently only 0 is supported", + protocol); + goto error; + } + + sock->state = SS_UNCONNECTED; + + err = -ENOBUFS; + sk = sk_alloc(net, PF_P2PKP, GFP_KERNEL, &p2pkp_proto); + if (unlikely(!sk)) { + ERROR("unable to create new socket"); + goto error; + } + + sock->ops = &p2pkp_ops; + sock_init_data(sock, sk); + + sk->sk_reuse = 1; + sk->sk_no_check = 1; + sk->sk_family = PF_P2PKP; + sk->sk_protocol = protocol; + sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; + + /* TODO init further data */ + ps = sock2p2pkp(sk); + + err = p2pkp_create_udp_sock(&ps->net_sock); + if (err < 0) { + ERROR("cannot create UDP socket"); + goto error; + } + ps->buffer_len = P2PKP_DEFAULT_BUF_LEN; + + INIT_LIST_HEAD(&ps->conn_list); + spin_lock_init(&ps->conn_lock); + + DEBUG("Created new P2PKP socket"); + + return 0; +error: + if (sk) + sock_put(sk); + return err; +} + + diff --git a/module/p2pkp_sock.h b/module/p2pkp_sock.h new file mode 100644 index 0000000..96d25aa --- /dev/null +++ b/module/p2pkp_sock.h @@ -0,0 +1,42 @@ +#ifndef _P2PKP_SOCKET_H_ +#define _P2PKP_SOCKET_H_ + +#include + +#define P2PKP_DEFAULT_BUF_LEN 256 + +struct p2pkp_conn_info { + struct sockaddr_in sin; + struct list_head list; +}; + +struct p2pkp_sock { + struct sock sk; + spinlock_t conn_lock; + struct list_head conn_list; + struct socket *net_sock; + unsigned int buffer_len; + unsigned char buffer[P2PKP_DEFAULT_BUF_LEN]; + int bind_ifindex; /* bound interface index; 0 for any interface */ + __be16 bind_port; /* bound port; 0 for unbound socks*/ + __be16 rem_port; /* remote port; 0 for unconnected socks */ +}; + +/* P2PKP protocol name; used as identifier in /proc/net/protocols */ +#define P2PKP_PROTO_NAME "P2PKP" + + +/* converts a sock to a p2pkp_sock */ +#define sock2p2pkp(sock) ((struct p2pkp_sock *)(sock)) +/* converts a p2pkp_sock to a sock */ +#define p2pkp2sock(ps) ((struct sock *)(ps)) + +/* converts a sockaddr to a sockaddr_p2pkp */ +#define sockaddr2p2pkp(sa) ((struct sockaddr_p2pkp *)(sa)) +/* converts a socaddr_p2pkp to a sockaddr */ +#define p2pkp2sockaddr(ps) ((struct sockaddr *)(ps)) + +int p2pkp_register_protocol(void); +void p2pkp_unregister_protocol(void); + +#endif /* _P2PKP_SOCKET_H_ */ diff --git a/module/p2psp.c b/module/p2psp.c deleted file mode 100644 index a29d930..0000000 --- a/module/p2psp.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Simple UDP implementation - * - * Răzvan Crainea - * Tudor Cazangiu - */ - -#include -#include -#include -#include -#include - -MODULE_DESCRIPTION("P2P Swift Protocol"); -MODULE_AUTHOR("Razvan Crainea and Tudor Cazangiu"); -MODULE_LICENSE("GPL"); - -#define LOG_LEVEL KERN_ALERT -#define P2PSP_LOCAL_PORT 60000 -#define P2PSP_REMOTE_PORT1 60001 -#define P2PSP_REMOTE_PORT2 60002 -#define MY_TEST_MESSAGE "kernelsocket\n" - -#define ON 1 -#define OFF 0 -#define DEBUG ON - -#if DEBUG == ON -#define LOG(s) \ - do { \ - printk(KERN_DEBUG s "\n"); \ - } while (0) -#else -#define LOG(s) \ - do {} while (0) -#endif - -#define print_sock_address(addr) \ - do { \ - printk(LOG_LEVEL "connection established to " \ - NIPQUAD_FMT ":%d\n", \ - NIPQUAD(addr.sin_addr.s_addr), \ - ntohs(addr.sin_port)); \ - } while (0) - -static struct socket *sock; /* UDP server */ - -/* send datagram */ -static int p2psp_msgsend(struct socket *s, short port) -{ - /* address to send to */ - struct sockaddr_in raddr = { - .sin_family = AF_INET, - .sin_port = htons(port), - .sin_addr = { htonl(INADDR_LOOPBACK) } - }; - int raddrlen = sizeof(raddr); - /* message */ - struct msghdr msg; - struct iovec iov; - char *buffer = MY_TEST_MESSAGE; - int len = strlen(buffer) + 1; - - /* build message */ - iov.iov_base = buffer; - iov.iov_len = len; - msg.msg_name = &raddr; - msg.msg_namelen = raddrlen; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - /* send the message down the socket */ - return kernel_sendmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len); -} - -int __init p2psp_sock_init(void) -{ - int err; - /* address to bind on */ - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_port = htons(P2PSP_LOCAL_PORT), - .sin_addr = { htonl(INADDR_LOOPBACK) } - }; - int addrlen = sizeof(addr); - - /* create UDP socket */ - err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); - if (err < 0) { - printk(LOG_LEVEL "can't create socket\n"); - goto out; - } - - /* bind socket to loopback on port P2PSP_LOCAL_PORT */ - err = sock->ops->bind(sock, (struct sockaddr *) &addr, addrlen); - if (err < 0) { - printk(LOG_LEVEL "can't bind socket\n"); - goto out_release; - } - - /* send first message */ - err = p2psp_msgsend(sock, P2PSP_REMOTE_PORT1); - if (err < 0) { - printk(LOG_LEVEL "can't send first message\n"); - goto out_release; - } - - /* send second message */ - err = p2psp_msgsend(sock, P2PSP_REMOTE_PORT2); - if (err < 0) { - printk(LOG_LEVEL "can't send second message\n"); - goto out_release; - } - - - return 0; - -out_release: - /* cleanup socket */ - sock_release(sock); -out: - return err; -} - -void __exit p2psp_sock_exit(void) -{ - /* cleanup socket */ - sock_release(sock); -} - -module_init(p2psp_sock_init); -module_exit(p2psp_sock_exit); diff --git a/module/test.sh b/module/test.sh deleted file mode 100755 index a26b09e..0000000 --- a/module/test.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -LISTENERS=2 -START_PORT=60001 - -#use nc.traditional -echo 2 | update-alternatives --config nc &> /dev/null - -#set -x - -# listen for UDP packets on localhost, port 60001 (run in background) -for listener in $(seq $LISTENERS); do - netcat -l -u -p $START_PORT & - pids="$pids $!" - START_PORT=$(($START_PORT + 1)) -done - -# wait for netcat to start listening -sleep 1 - -# insert module, causing the message to be sent -insmod p2psp.ko - -# remove module -rmmod p2psp - -# kill netcat -for pid in $pids; do - kill $pid &> /dev/null -done diff --git a/test/client/Makefile b/test/client/Makefile new file mode 100644 index 0000000..8d5c7ad --- /dev/null +++ b/test/client/Makefile @@ -0,0 +1,7 @@ +FILE=client + +$(FILE):$(FILE).o + +.PHONY: clean +clean: + -rm -rf $(FILE) $(FILE).o diff --git a/test/client/client b/test/client/client new file mode 100755 index 0000000..6f7edef Binary files /dev/null and b/test/client/client differ diff --git a/test/client/client.c b/test/client/client.c new file mode 100644 index 0000000..1e70583 --- /dev/null +++ b/test/client/client.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "p2pkp.h" + +#define TEST_FILE "/root/Dropbox/school/p2pkp/test/client/test_file" + +int main(int argc, char **argv) +{ + int sock, err; + struct sockaddr_in psin; + struct hostent *host; + + if (argc % 2 == 0 || argc < 2) { + fprintf(stderr, "Usage: %s " + " ...\n", argv[0]); + return -1; + } + + printf("Opening AF_P2PKP socket\n"); + + sock = socket(AF_P2PKP, SOCK_DGRAM, 0); + printf("Socket returned: %d\n", sock); + + if (sock < 0) { + printf("Cannot create AF_P2PKP socket: %s(%d)\n", + strerror(errno), errno); + return -1; + } + printf("Successfully created AF_P2PKP socket: %d\n", sock); + + argv++; + while (*argv) { + printf("Connecting to: %s:%s\n", argv[0], argv[1]); + + host = gethostbyname(argv[0]); + psin.sin_family = AF_INET; + psin.sin_port = htons(atoi(argv[1])); + psin.sin_addr = *((struct in_addr *)host->h_addr); + + if (connect(sock, (struct sockaddr *)&psin, + sizeof(struct sockaddr_in)) == -1) + { + printf("Cannot connect to server: %s(%d)\n", strerror(errno), errno); + return -1; + } + printf("Connected to: %s:%s\n", argv[0], argv[1]); + argv+=2; + } + + printf("Starting to write on the socket\n"); + + err = write(sock, TEST_FILE, sizeof(TEST_FILE) - 1); + if (err < 0) { + printf("Error while sending file %s: %s(%d)\n", TEST_FILE, + strerror(errno), errno); + return err; + } + + printf("Successfully written file\n"); + + return 0; +} diff --git a/test/client/p2pkp.h b/test/client/p2pkp.h new file mode 100644 index 0000000..f18d258 --- /dev/null +++ b/test/client/p2pkp.h @@ -0,0 +1,7 @@ +#ifndef _P2PKP_H_ +#define _P2PKP_H_ + +#define AF_P2PKP 19 +#define PF_P2PKP AF_P2PKP + +#endif /* _P2PKP_H_ */ diff --git a/test/client/test.sh b/test/client/test.sh new file mode 100755 index 0000000..b961f72 --- /dev/null +++ b/test/client/test.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +MODULE_NAME=af_p2pkp +MODULE_DIR=../../module +CLIENT=./client + +LISTENERS_PORTS=( + 60000 + 60001 + 60002 +) + + +#use nc.traditional +echo 2 | update-alternatives --config nc &> /dev/null + +#increase tests debugging +set -x + +# listen for UDP packets on localhost, port 60000 (run in background) +for listener in "${LISTENERS_PORTS[@]}"; do + netcat -l -u -p $listener & + pids="$pids $!" + ARGUMENTS="127.0.0.1 $listener $ARGUMENTS" +done + +# wait for netcat to start listening +sleep 1 + +# insert module, causing the message to be sent +insmod $MODULE_DIR/$MODULE_NAME.ko + +$CLIENT $ARGUMENTS + +# remove module +rmmod $MODULE_NAME + +# kill netcat +for pid in $pids; do + kill $pid &> /dev/null +done diff --git a/test/client/test_file b/test/client/test_file new file mode 100644 index 0000000..fc5ca98 --- /dev/null +++ b/test/client/test_file @@ -0,0 +1,2 @@ +TEST 1 +TEST 2