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)
return IS_ERR_OR_NULL(file) ? NULL : file;
}
+struct file* p2pkp_open_file_write(const char *filename, mode_t mode)
+{
+ struct file * file;
+ file = filp_open(filename, O_CREAT|O_TRUNC, mode);
+ return IS_ERR_OR_NULL(file) ? NULL : file;
+}
+
void p2pkp_close_file(struct file *file)
{
filp_close(file,NULL);
}
+int p2pkp_write_in_file(struct file *file, char *buffer, int len)
+{
+ // Create variables
+ int bytes_written, ret;
+ mm_segment_t fs;
+
+ 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);
+
+ bytes_written = 0;
+ do {
+ ret = file->f_op->write(file, buffer + bytes_written, len, &file->f_pos);
+ if (ret < 0) {
+ ERROR("error while reading from file");
+ break;
+ }
+ len -= ret;
+ bytes_written += ret;
+ } while (len > 0);
+
+ set_fs(fs);
+
+ return ret < 0 ? ret : bytes_written;
+}
+
+
+
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;
struct file* p2pkp_open_file_read(const char *filename);
+struct file* p2pkp_open_file_write(const char *filename, mode_t mode);
void p2pkp_close_file(struct file *file);
int p2pkp_read_from_file(struct file *file, char *buffer, int len);
+int p2pkp_write_in_file(struct file *file, char *buffer, int len);
#endif /* _P2PKP_FILE_H_ */
return kernel_sendmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len);
}
+/* receive datagram */
+int p2pkp_msgrecv(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_recvmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len, 0);
+}
+
+
int p2pkp_create_udp_sock(struct socket **sock)
{
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);
+int p2pkp_msgrecv(struct socket *s, struct sockaddr_in *sin, char *buffer, int len);
#endif /* _P2PKP_NET_H_ */
}
static int p2pkp_bind(struct socket *sock, struct sockaddr *myaddr,
- int sockaddr_len){return 0;}
+ int sockaddr_len)
+{
+ struct sock *sk = sock->sk;
+ struct p2pkp_sock *ps = sock2p2pkp(sk);
+ struct sockaddr_in *sin = (struct sockaddr_in *)myaddr;
+ int err = 0;
+
+ if (!sock || !myaddr || sockaddr_len != sizeof(struct sockaddr_in) ||
+ sin->sin_family != AF_INET) {
+ ERROR("invalid parameters for bind");
+ return -EINVAL;
+ }
+
+ lock_sock(sk);
+ err = ps->net_sock->ops->bind(ps->net_sock, myaddr, sockaddr_len);
+ if (err < 0) {
+ ERROR("can't bind socket");
+ }
+ release_sock(sk);
+ return err;
+}
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)
{
- int err = -ENXIO;
- int f_index, bytes_read;
+ int err = 0;
+ int f_index, bytes_read, files_no = 0;
struct sock *sk = sock->sk;
struct p2pkp_sock *ps = sock2p2pkp(sk);
struct sockaddr_in *sin = (struct sockaddr_in *)m->msg_name;
/* check if the file exists */
for (f_index = 0; f_index < m->msg_iovlen; f_index++) {
+ err = 0;
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);
+ err = -ENOENT;
continue;
}
DEBUG("opened file %s", file_name);
DEBUG("read %d bytes from file", bytes_read);
if (bytes_read < 0) {
ERROR("cannot read from file");
+ err = bytes_read;
goto out_close;
}
if (bytes_read == 0)
goto out_conn;
}
}
+ files_no++;
out_conn:
release_sock(sk);
}
p2pkp_close_file(file);
}
-
DEBUG("Sending completed successfully");
- err = 0;
release:
release_sock(sk);
- return err;
+ return err ? err : files_no;
}
static int p2pkp_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *m, size_t total_len, int flags){return 0;}
+ struct msghdr *m, size_t total_len, int flags)
+{
+ int err = -ENXIO;
+ int bytes_read, bytes_written;
+ 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 = (char *)m->msg_iov[0].iov_base;
+ mode_t mode = P2PKP_DEFAULT_MODE;
+
+ /* first try to get some files */
+ if (!sock || !m || !file_name) {
+ ERROR("invalid socket parameters");
+ return -EINVAL;
+ }
+
+ file = p2pkp_open_file_write(file_name, mode);
+ if (!file) {
+ ERROR("cannot open file %s\n", file_name);
+ return -ENOENT;
+ }
+
+ lock_sock(sk);
+ /* TODO keep connections */
+ bytes_read = p2pkp_msgrecv(ps->net_sock, sin, ps->buffer, ps->buffer_len);
+ if (bytes_read > 0) {
+ bytes_written = p2pkp_write_in_file(file, ps->buffer, bytes_read);
+ err = 0;
+ } else if (bytes_read < 0) {
+ ERROR("cannot read data");
+ err = -ENXIO;
+ }
+ release_sock(sk);
+ p2pkp_close_file(file);
+
+ return err ? err : bytes_written;
+}
static int p2pkp_create(struct net *net, struct socket *sock, int protocol,
sock_put(sk);
return err;
}
-
-
#include <net/sock.h>
#define P2PKP_DEFAULT_BUF_LEN 256
+#define P2PKP_DEFAULT_MODE 0644
struct p2pkp_conn_info {
struct sockaddr_in sin;