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 @@ ...@@ -31,6 +31,8 @@
#include <linux/ncp_fs.h> #include <linux/ncp_fs.h>
#include <net/sock.h>
#include "ncplib_kernel.h" #include "ncplib_kernel.h"
#include "getopt.h" #include "getopt.h"
...@@ -284,6 +286,16 @@ ncp_delete_inode(struct inode *inode) ...@@ -284,6 +286,16 @@ ncp_delete_inode(struct inode *inode)
clear_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[] = { static const struct ncp_option ncp_opts[] = {
{ "uid", OPT_INT, 'u' }, { "uid", OPT_INT, 'u' },
{ "gid", OPT_INT, 'g' }, { "gid", OPT_INT, 'g' },
...@@ -464,6 +476,8 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -464,6 +476,8 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
memset(server, 0, sizeof(*server)); memset(server, 0, sizeof(*server));
server->ncp_filp = ncp_filp; server->ncp_filp = ncp_filp;
server->ncp_sock = sock;
/* server->lock = 0; */ /* server->lock = 0; */
init_MUTEX(&server->sem); init_MUTEX(&server->sem);
server->packet = NULL; server->packet = NULL;
...@@ -501,6 +515,16 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -501,6 +515,16 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
server->dentry_ttl = 0; /* no caching */ 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 #undef NCP_PACKET_SIZE
#define NCP_PACKET_SIZE 131072 #define NCP_PACKET_SIZE 131072
error = -ENOMEM; error = -ENOMEM;
...@@ -509,6 +533,22 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -509,6 +533,22 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
if (server->packet == NULL) if (server->packet == NULL)
goto out_nls; 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); ncp_lock_server(server);
error = ncp_connect(server); error = ncp_connect(server);
ncp_unlock_server(server); ncp_unlock_server(server);
...@@ -583,6 +623,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) ...@@ -583,6 +623,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
ncp_disconnect(server); ncp_disconnect(server);
ncp_unlock_server(server); ncp_unlock_server(server);
out_packet: out_packet:
ncp_stop_tasks(server);
vfree(server->packet); vfree(server->packet);
out_nls: out_nls:
#ifdef CONFIG_NCPFS_NLS #ifdef CONFIG_NCPFS_NLS
...@@ -610,6 +651,8 @@ static void ncp_put_super(struct super_block *sb) ...@@ -610,6 +651,8 @@ static void ncp_put_super(struct super_block *sb)
ncp_disconnect(server); ncp_disconnect(server);
ncp_unlock_server(server); ncp_unlock_server(server);
ncp_stop_tasks(server);
#ifdef CONFIG_NCPFS_NLS #ifdef CONFIG_NCPFS_NLS
/* unload the NLS charsets */ /* unload the NLS charsets */
if (server->nls_vol) if (server->nls_vol)
......
...@@ -93,19 +93,19 @@ static void nwsign(char *r_data1, char *r_data2, char *outdata) { ...@@ -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 */ /* Make a signature for the current packet and add it at the end of the */
/* packet. */ /* packet. */
void sign_packet(struct ncp_server *server, int *size) { void __sign_packet(struct ncp_server *server, const char *packet, size_t size, __u32 totalsize, void *sign_buff) {
char data[64]; unsigned char data[64];
memset(data,0,64); memcpy(data, server->sign_root, 8);
memcpy(data,server->sign_root,8); *(__u32*)(data + 8) = totalsize;
PUT_LE32(data+8,(*size)); if (size < 52) {
memcpy(data+12,server->packet+sizeof(struct ncp_request_header)-1, memcpy(data + 12, packet, size);
min_t(unsigned int,(*size)-sizeof(struct ncp_request_header)+1,52)); memset(data + 12 + size, 0, 52 - size);
} else {
nwsign(server->sign_last,data,server->sign_last); memcpy(data + 12, packet, 52);
}
memcpy(server->packet+(*size),server->sign_last,8); nwsign(server->sign_last, data, server->sign_last);
(*size)+=8; memcpy(sign_buff, server->sign_last, 8);
} }
#endif /* CONFIG_NCPFS_PACKET_SIGNING */ #endif /* CONFIG_NCPFS_PACKET_SIGNING */
......
...@@ -10,6 +10,18 @@ ...@@ -10,6 +10,18 @@
#include <linux/ncp_fs.h> #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 #endif
This diff is collapsed.
...@@ -30,6 +30,7 @@ struct ncp_request_header { ...@@ -30,6 +30,7 @@ struct ncp_request_header {
}; };
#define NCP_REPLY (0x3333) #define NCP_REPLY (0x3333)
#define NCP_WATCHDOG (0x3E3E)
#define NCP_POSITIVE_ACK (0x9999) #define NCP_POSITIVE_ACK (0x9999)
struct ncp_reply_header { struct ncp_reply_header {
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/tqueue.h>
#define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */ #define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */
struct ncp_server { struct ncp_server {
...@@ -24,6 +26,7 @@ struct ncp_server { ...@@ -24,6 +26,7 @@ struct ncp_server {
__u8 name_space[NCP_NUMBER_OF_VOLUMES + 2]; __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2];
struct file *ncp_filp; /* File pointer to ncp socket */ struct file *ncp_filp; /* File pointer to ncp socket */
struct socket *ncp_sock;/* ncp socket */
u8 sequence; u8 sequence;
u8 task; u8 task;
...@@ -79,8 +82,50 @@ struct ncp_server { ...@@ -79,8 +82,50 @@ struct ncp_server {
/* miscellaneous */ /* miscellaneous */
unsigned int flags; 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_FLAG_UTF8 1
#define NCP_CLR_FLAG(server, flag) ((server)->flags &= ~(flag)) #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