Commit 32758c3b authored by Petr Vandrovec's avatar Petr Vandrovec

ncpfs: Proper handling of watchdog packets.

ncpfs: Add support for packet signatures when using TCP transport.
parent 8612e088
......@@ -31,6 +31,8 @@
#include <linux/ncp_fs.h>
#include <net/sock.h>
#include "ncplib_kernel.h"
#include "getopt.h"
......@@ -284,6 +286,16 @@ ncp_delete_inode(struct inode *inode)
clear_inode(inode);
}
static void ncp_stop_tasks(struct ncp_server *server) {
struct sock* sk = server->ncp_sock->sk;
sk->error_report = server->error_report;
sk->data_ready = server->data_ready;
sk->write_space = server->write_space;
del_timer_sync(&server->timeout_tm);
flush_scheduled_tasks();
}
static const struct ncp_option ncp_opts[] = {
{ "uid", OPT_INT, 'u' },
{ "gid", OPT_INT, 'g' },
......@@ -464,6 +476,8 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
memset(server, 0, sizeof(*server));
server->ncp_filp = ncp_filp;
server->ncp_sock = sock;
/* server->lock = 0; */
init_MUTEX(&server->sem);
server->packet = NULL;
......@@ -501,6 +515,16 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
server->dentry_ttl = 0; /* no caching */
INIT_LIST_HEAD(&server->tx.requests);
init_MUTEX(&server->rcv.creq_sem);
server->tx.creq = NULL;
server->rcv.creq = NULL;
server->data_ready = sock->sk->data_ready;
server->write_space = sock->sk->write_space;
server->error_report = sock->sk->error_report;
sock->sk->user_data = server;
init_timer(&server->timeout_tm);
#undef NCP_PACKET_SIZE
#define NCP_PACKET_SIZE 131072
error = -ENOMEM;
......@@ -509,6 +533,22 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
if (server->packet == NULL)
goto out_nls;
sock->sk->data_ready = ncp_tcp_data_ready;
sock->sk->error_report = ncp_tcp_error_report;
if (sock->type == SOCK_STREAM) {
server->rcv.ptr = (unsigned char*)&server->rcv.buf;
server->rcv.len = 10;
server->rcv.state = 0;
INIT_TQUEUE(&server->rcv.tq, ncp_tcp_rcv_proc, server);
INIT_TQUEUE(&server->tx.tq, ncp_tcp_tx_proc, server);
sock->sk->write_space = ncp_tcp_write_space;
} else {
INIT_TQUEUE(&server->rcv.tq, ncpdgram_rcv_proc, server);
INIT_TQUEUE(&server->timeout_tq, ncpdgram_timeout_proc, server);
server->timeout_tm.data = (unsigned long)server;
server->timeout_tm.function = ncpdgram_timeout_call;
}
ncp_lock_server(server);
error = ncp_connect(server);
ncp_unlock_server(server);
......@@ -583,6 +623,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
ncp_disconnect(server);
ncp_unlock_server(server);
out_packet:
ncp_stop_tasks(server);
vfree(server->packet);
out_nls:
#ifdef CONFIG_NCPFS_NLS
......@@ -610,6 +651,8 @@ static void ncp_put_super(struct super_block *sb)
ncp_disconnect(server);
ncp_unlock_server(server);
ncp_stop_tasks(server);
#ifdef CONFIG_NCPFS_NLS
/* unload the NLS charsets */
if (server->nls_vol)
......
......@@ -93,19 +93,19 @@ static void nwsign(char *r_data1, char *r_data2, char *outdata) {
/* Make a signature for the current packet and add it at the end of the */
/* packet. */
void sign_packet(struct ncp_server *server, int *size) {
char data[64];
void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) {
unsigned char data[64];
memset(data,0,64);
memcpy(data,server->sign_root,8);
PUT_LE32(data+8,(*size));
memcpy(data+12,server->packet+sizeof(struct ncp_request_header)-1,
min_t(unsigned int,(*size)-sizeof(struct ncp_request_header)+1,52));
nwsign(server->sign_last,data,server->sign_last);
memcpy(server->packet+(*size),server->sign_last,8);
(*size)+=8;
memcpy(data, server->sign_root, 8);
*(__u32*)(data + 8) = totalsize;
if (size < 52) {
memcpy(data + 12, packet, size);
memset(data + 12 + size, 0, 52 - size);
} else {
memcpy(data + 12, packet, 52);
}
nwsign(server->sign_last, data, server->sign_last);
memcpy(sign_buff, server->sign_last, 8);
}
#endif /* CONFIG_NCPFS_PACKET_SIGNING */
......
......@@ -10,6 +10,18 @@
#include <linux/ncp_fs.h>
void sign_packet(struct ncp_server *server, int *size);
#ifdef CONFIG_NCPFS_PACKET_SIGNING
void __sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff);
#endif
static inline size_t sign_packet(struct ncp_server *server, const char *data, size_t size, __u32 totalsize, void *sign_buff) {
#ifdef CONFIG_NCPFS_PACKET_SIGNING
if (server->sign_active) {
__sign_packet(server, data, size, totalsize, sign_buff);
return 8;
}
#endif
return 0;
}
#endif
This diff is collapsed.
......@@ -30,6 +30,7 @@ struct ncp_request_header {
};
#define NCP_REPLY (0x3333)
#define NCP_WATCHDOG (0x3E3E)
#define NCP_POSITIVE_ACK (0x9999)
struct ncp_reply_header {
......
......@@ -13,6 +13,8 @@
#ifdef __KERNEL__
#include <linux/tqueue.h>
#define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */
struct ncp_server {
......@@ -24,6 +26,7 @@ struct ncp_server {
__u8 name_space[NCP_NUMBER_OF_VOLUMES + 2];
struct file *ncp_filp; /* File pointer to ncp socket */
struct socket *ncp_sock;/* ncp socket */
u8 sequence;
u8 task;
......@@ -79,8 +82,50 @@ struct ncp_server {
/* miscellaneous */
unsigned int flags;
spinlock_t requests_lock; /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */
void (*data_ready)(struct sock* sk, int len);
void (*error_report)(struct sock* sk);
void (*write_space)(struct sock* sk); /* STREAM mode only */
struct {
struct tq_struct tq; /* STREAM/DGRAM: data/error ready */
struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */
struct semaphore creq_sem; /* DGRAM only: lock accesses to rcv.creq */
unsigned int state; /* STREAM only: receiver state */
struct {
__u32 magic __attribute__((packed));
__u32 len __attribute__((packed));
__u16 type __attribute__((packed));
__u16 p1 __attribute__((packed));
__u16 p2 __attribute__((packed));
__u16 p3 __attribute__((packed));
__u16 type2 __attribute__((packed));
} buf; /* STREAM only: temporary buffer */
unsigned char* ptr; /* STREAM only: pointer to data */
size_t len; /* STREAM only: length of data to receive */
} rcv;
struct {
struct list_head requests; /* STREAM only: queued requests */
struct tq_struct tq; /* STREAM only: transmitter ready */
struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */
} tx;
struct timer_list timeout_tm; /* DGRAM only: timeout timer */
struct tq_struct timeout_tq; /* DGRAM only: associated queue, we run timers from process context */
int timeout_last; /* DGRAM only: current timeout length */
int timeout_retries; /* DGRAM only: retries left */
};
extern void ncp_tcp_rcv_proc(void *server);
extern void ncp_tcp_tx_proc(void *server);
extern void ncpdgram_rcv_proc(void *server);
extern void ncpdgram_timeout_proc(void *server);
extern void ncpdgram_timeout_call(unsigned long server);
extern void ncp_tcp_data_ready(struct sock* sk, int len);
extern void ncp_tcp_write_space(struct sock* sk);
extern void ncp_tcp_error_report(struct sock* sk);
#define NCP_FLAG_UTF8 1
#define NCP_CLR_FLAG(server, flag) ((server)->flags &= ~(flag))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment