Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
32758c3b
Commit
32758c3b
authored
Sep 21, 2002
by
Petr Vandrovec
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ncpfs: Proper handling of watchdog packets.
ncpfs: Add support for packet signatures when using TCP transport.
parent
8612e088
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
676 additions
and
366 deletions
+676
-366
fs/ncpfs/inode.c
fs/ncpfs/inode.c
+43
-0
fs/ncpfs/ncpsign_kernel.c
fs/ncpfs/ncpsign_kernel.c
+12
-12
fs/ncpfs/ncpsign_kernel.h
fs/ncpfs/ncpsign_kernel.h
+13
-1
fs/ncpfs/sock.c
fs/ncpfs/sock.c
+562
-353
include/linux/ncp.h
include/linux/ncp.h
+1
-0
include/linux/ncp_fs_sb.h
include/linux/ncp_fs_sb.h
+45
-0
No files found.
fs/ncpfs/inode.c
View file @
32758c3b
...
@@ -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
)
...
...
fs/ncpfs/ncpsign_kernel.c
View file @
32758c3b
...
@@ -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 */
...
...
fs/ncpfs/ncpsign_kernel.h
View file @
32758c3b
...
@@ -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
fs/ncpfs/sock.c
View file @
32758c3b
...
@@ -29,18 +29,13 @@
...
@@ -29,18 +29,13 @@
#include <linux/ncp_fs.h>
#include <linux/ncp_fs.h>
#ifdef CONFIG_NCPFS_PACKET_SIGNING
#include "ncpsign_kernel.h"
#include "ncpsign_kernel.h"
#endif
static
int
_recv
(
struct
socket
*
sock
,
unsigned
char
*
ubuf
,
int
size
,
static
int
_recv
(
struct
socket
*
sock
,
unsigned
char
*
ubuf
,
int
size
,
unsigned
flags
)
unsigned
flags
)
{
{
struct
iovec
iov
;
struct
iovec
iov
;
struct
msghdr
msg
;
struct
msghdr
msg
;
struct
scm_cookie
scm
;
memset
(
&
scm
,
0
,
sizeof
(
scm
));
iov
.
iov_base
=
ubuf
;
iov
.
iov_base
=
ubuf
;
iov
.
iov_len
=
size
;
iov
.
iov_len
=
size
;
...
@@ -50,15 +45,14 @@ static int _recv(struct socket *sock, unsigned char *ubuf, int size,
...
@@ -50,15 +45,14 @@ static int _recv(struct socket *sock, unsigned char *ubuf, int size,
msg
.
msg_control
=
NULL
;
msg
.
msg_control
=
NULL
;
msg
.
msg_iov
=
&
iov
;
msg
.
msg_iov
=
&
iov
;
msg
.
msg_iovlen
=
1
;
msg
.
msg_iovlen
=
1
;
return
sock
->
ops
->
recvmsg
(
sock
,
&
msg
,
size
,
flags
,
&
scm
);
return
sock_recvmsg
(
sock
,
&
msg
,
size
,
flags
);
}
}
static
int
_send
(
struct
socket
*
sock
,
const
void
*
buff
,
int
len
)
static
in
line
in
t
_send
(
struct
socket
*
sock
,
const
void
*
buff
,
int
len
)
{
{
struct
iovec
iov
;
struct
iovec
iov
;
struct
msghdr
msg
;
struct
msghdr
msg
;
struct
scm_cookie
scm
;
int
err
;
iov
.
iov_base
=
(
void
*
)
buff
;
iov
.
iov_base
=
(
void
*
)
buff
;
iov
.
iov_len
=
len
;
iov
.
iov_len
=
len
;
...
@@ -70,353 +64,599 @@ static int _send(struct socket *sock, const void *buff, int len)
...
@@ -70,353 +64,599 @@ static int _send(struct socket *sock, const void *buff, int len)
msg
.
msg_iovlen
=
1
;
msg
.
msg_iovlen
=
1
;
msg
.
msg_flags
=
0
;
msg
.
msg_flags
=
0
;
err
=
scm_send
(
sock
,
&
msg
,
&
scm
);
return
sock_sendmsg
(
sock
,
&
msg
,
len
);
if
(
err
<
0
)
{
}
return
err
;
struct
ncp_request_reply
{
struct
list_head
req
;
wait_queue_head_t
wq
;
struct
ncp_reply_header
*
reply_buf
;
size_t
datalen
;
int
result
;
enum
{
RQ_DONE
,
RQ_INPROGRESS
,
RQ_QUEUED
,
RQ_IDLE
}
status
;
struct
iovec
*
tx_ciov
;
size_t
tx_totallen
;
size_t
tx_iovlen
;
struct
iovec
tx_iov
[
3
];
u_int16_t
tx_type
;
u_int32_t
sign
[
6
];
};
void
ncp_tcp_data_ready
(
struct
sock
*
sk
,
int
len
)
{
struct
ncp_server
*
server
=
sk
->
user_data
;
server
->
data_ready
(
sk
,
len
);
schedule_task
(
&
server
->
rcv
.
tq
);
}
void
ncp_tcp_error_report
(
struct
sock
*
sk
)
{
struct
ncp_server
*
server
=
sk
->
user_data
;
server
->
error_report
(
sk
);
schedule_task
(
&
server
->
rcv
.
tq
);
}
void
ncp_tcp_write_space
(
struct
sock
*
sk
)
{
struct
ncp_server
*
server
=
sk
->
user_data
;
/* We do not need any locking: we first set tx.creq, and then we do sendmsg,
not vice versa... */
server
->
write_space
(
sk
);
if
(
server
->
tx
.
creq
)
{
schedule_task
(
&
server
->
tx
.
tq
);
}
}
err
=
sock
->
ops
->
sendmsg
(
sock
,
&
msg
,
len
,
&
scm
);
scm_destroy
(
&
scm
);
return
err
;
}
}
static
int
do_ncp_rpc_call
(
struct
ncp_server
*
server
,
int
size
,
void
ncpdgram_timeout_call
(
unsigned
long
v
)
{
struct
ncp_reply_header
*
reply_buf
,
int
max_reply_size
)
struct
ncp_server
*
server
=
(
void
*
)
v
;
{
struct
file
*
file
;
schedule_task
(
&
server
->
timeout_tq
);
struct
socket
*
sock
;
}
static
inline
void
ncp_finish_request
(
struct
ncp_request_reply
*
req
,
int
result
)
{
req
->
result
=
result
;
req
->
status
=
RQ_DONE
;
wake_up_all
(
&
req
->
wq
);
}
static
void
__abort_ncp_connection
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
aborted
,
int
err
)
{
struct
ncp_request_reply
*
req
;
ncp_invalidate_conn
(
server
);
del_timer
(
&
server
->
timeout_tm
);
while
(
!
list_empty
(
&
server
->
tx
.
requests
))
{
req
=
list_entry
(
server
->
tx
.
requests
.
next
,
struct
ncp_request_reply
,
req
);
list_del_init
(
&
req
->
req
);
if
(
req
==
aborted
)
{
ncp_finish_request
(
req
,
err
);
}
else
{
ncp_finish_request
(
req
,
-
EIO
);
}
}
req
=
server
->
rcv
.
creq
;
if
(
req
)
{
server
->
rcv
.
creq
=
NULL
;
if
(
req
==
aborted
)
{
ncp_finish_request
(
req
,
err
);
}
else
{
ncp_finish_request
(
req
,
-
EIO
);
}
server
->
rcv
.
ptr
=
NULL
;
server
->
rcv
.
state
=
0
;
}
req
=
server
->
tx
.
creq
;
if
(
req
)
{
server
->
tx
.
creq
=
NULL
;
if
(
req
==
aborted
)
{
ncp_finish_request
(
req
,
err
);
}
else
{
ncp_finish_request
(
req
,
-
EIO
);
}
}
}
static
inline
int
get_conn_number
(
struct
ncp_reply_header
*
rp
)
{
return
rp
->
conn_low
|
(
rp
->
conn_high
<<
8
);
}
static
inline
void
__ncp_abort_request
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
req
,
int
err
)
{
/* If req is done, we got signal, but we also received answer... */
switch
(
req
->
status
)
{
case
RQ_IDLE
:
case
RQ_DONE
:
break
;
case
RQ_QUEUED
:
list_del_init
(
&
req
->
req
);
ncp_finish_request
(
req
,
err
);
break
;
case
RQ_INPROGRESS
:
__abort_ncp_connection
(
server
,
req
,
err
);
break
;
}
}
static
inline
void
ncp_abort_request
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
req
,
int
err
)
{
down
(
&
server
->
rcv
.
creq_sem
);
__ncp_abort_request
(
server
,
req
,
err
);
up
(
&
server
->
rcv
.
creq_sem
);
}
static
inline
void
__ncptcp_abort
(
struct
ncp_server
*
server
)
{
__abort_ncp_connection
(
server
,
NULL
,
0
);
}
static
int
ncpdgram_send
(
struct
socket
*
sock
,
struct
ncp_request_reply
*
req
)
{
struct
msghdr
msg
;
msg
.
msg_name
=
NULL
;
msg
.
msg_namelen
=
0
;
msg
.
msg_control
=
NULL
;
msg
.
msg_iov
=
req
->
tx_ciov
;
msg
.
msg_iovlen
=
req
->
tx_iovlen
;
msg
.
msg_flags
=
MSG_DONTWAIT
;
return
sock_sendmsg
(
sock
,
&
msg
,
req
->
tx_totallen
);
}
static
void
__ncptcp_try_send
(
struct
ncp_server
*
server
)
{
struct
ncp_request_reply
*
rq
;
struct
msghdr
msg
;
struct
iovec
*
iov
;
int
result
;
int
result
;
char
*
start
=
server
->
packet
;
poll_table
wait_table
;
int
init_timeout
,
max_timeout
;
int
timeout
;
int
retrans
;
int
major_timeout_seen
;
int
acknowledge_seen
;
int
n
;
/* We have to check the result, so store the complete header */
rq
=
server
->
tx
.
creq
;
struct
ncp_request_header
request
=
if
(
!
rq
)
{
*
((
struct
ncp_request_header
*
)
(
server
->
packet
));
return
;
}
struct
ncp_reply_header
reply
;
msg
.
msg_name
=
NULL
;
file
=
server
->
ncp_filp
;
msg
.
msg_namelen
=
0
;
sock
=
SOCKET_I
(
file
->
f_dentry
->
d_inode
);
msg
.
msg_control
=
NULL
;
msg
.
msg_iov
=
rq
->
tx_ciov
;
init_timeout
=
server
->
m
.
time_out
;
msg
.
msg_iovlen
=
rq
->
tx_iovlen
;
max_timeout
=
NCP_MAX_RPC_TIMEOUT
;
msg
.
msg_flags
=
MSG_NOSIGNAL
|
MSG_DONTWAIT
;
retrans
=
server
->
m
.
retry_count
;
result
=
sock_sendmsg
(
server
->
ncp_sock
,
&
msg
,
rq
->
tx_totallen
);
major_timeout_seen
=
0
;
if
(
result
==
-
EAGAIN
)
{
acknowledge_seen
=
0
;
return
;
}
for
(
n
=
0
,
timeout
=
init_timeout
;;
n
++
,
timeout
<<=
1
)
{
if
(
result
<
0
)
{
/*
printk
(
KERN_ERR
"ncpfs: tcp: Send failed: %d
\n
"
,
result
);
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
__ncp_abort_request
(
server
,
rq
,
result
);
htonl(server->m.serv_addr.sipx_network),
return
;
server->m.serv_addr.sipx_node[0],
}
server->m.serv_addr.sipx_node[1],
if
(
result
>=
rq
->
tx_totallen
)
{
server->m.serv_addr.sipx_node[2],
server
->
rcv
.
creq
=
rq
;
server->m.serv_addr.sipx_node[3],
server
->
tx
.
creq
=
NULL
;
server->m.serv_addr.sipx_node[4],
return
;
server->m.serv_addr.sipx_node[5],
}
ntohs(server->m.serv_addr.sipx_port));
rq
->
tx_totallen
-=
result
;
*/
iov
=
rq
->
tx_ciov
;
DDPRINTK
(
"ncpfs: req.typ: %04X, con: %d, "
while
(
iov
->
iov_len
<=
result
)
{
"seq: %d"
,
result
-=
iov
->
iov_len
;
request
.
type
,
iov
++
;
(
request
.
conn_high
<<
8
)
+
request
.
conn_low
,
rq
->
tx_iovlen
--
;
request
.
sequence
);
}
DDPRINTK
(
" func: %d
\n
"
,
iov
->
iov_len
-=
result
;
request
.
function
);
rq
->
tx_ciov
=
iov
;
}
result
=
_send
(
sock
,
(
void
*
)
start
,
size
);
static
inline
void
ncp_init_header
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
req
,
struct
ncp_request_header
*
h
)
{
req
->
status
=
RQ_INPROGRESS
;
h
->
conn_low
=
server
->
connection
;
h
->
conn_high
=
server
->
connection
>>
8
;
h
->
sequence
=
++
server
->
sequence
;
}
static
void
ncpdgram_start_request
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
req
)
{
size_t
signlen
;
struct
ncp_request_header
*
h
;
req
->
tx_ciov
=
req
->
tx_iov
+
1
;
h
=
req
->
tx_iov
[
1
].
iov_base
;
ncp_init_header
(
server
,
req
,
h
);
signlen
=
sign_packet
(
server
,
req
->
tx_iov
[
1
].
iov_base
+
sizeof
(
struct
ncp_request_header
)
-
1
,
req
->
tx_iov
[
1
].
iov_len
-
sizeof
(
struct
ncp_request_header
)
+
1
,
cpu_to_le32
(
req
->
tx_totallen
),
req
->
sign
);
if
(
signlen
)
{
req
->
tx_ciov
[
1
].
iov_base
=
req
->
sign
;
req
->
tx_ciov
[
1
].
iov_len
=
signlen
;
req
->
tx_iovlen
+=
1
;
req
->
tx_totallen
+=
signlen
;
}
server
->
rcv
.
creq
=
req
;
server
->
timeout_last
=
server
->
m
.
time_out
;
server
->
timeout_retries
=
server
->
m
.
retry_count
;
ncpdgram_send
(
server
->
ncp_sock
,
req
);
mod_timer
(
&
server
->
timeout_tm
,
jiffies
+
server
->
m
.
time_out
);
}
#define NCP_TCP_XMIT_MAGIC (0x446D6454)
#define NCP_TCP_XMIT_VERSION (1)
#define NCP_TCP_RCVD_MAGIC (0x744E6350)
static
void
ncptcp_start_request
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
req
)
{
size_t
signlen
;
struct
ncp_request_header
*
h
;
req
->
tx_ciov
=
req
->
tx_iov
;
h
=
req
->
tx_iov
[
1
].
iov_base
;
ncp_init_header
(
server
,
req
,
h
);
signlen
=
sign_packet
(
server
,
req
->
tx_iov
[
1
].
iov_base
+
sizeof
(
struct
ncp_request_header
)
-
1
,
req
->
tx_iov
[
1
].
iov_len
-
sizeof
(
struct
ncp_request_header
)
+
1
,
cpu_to_be32
(
req
->
tx_totallen
+
24
),
req
->
sign
+
4
)
+
16
;
req
->
sign
[
0
]
=
htonl
(
NCP_TCP_XMIT_MAGIC
);
req
->
sign
[
1
]
=
htonl
(
req
->
tx_totallen
+
signlen
);
req
->
sign
[
2
]
=
htonl
(
NCP_TCP_XMIT_VERSION
);
req
->
sign
[
3
]
=
htonl
(
req
->
datalen
+
8
);
req
->
tx_iov
[
0
].
iov_base
=
req
->
sign
;
req
->
tx_iov
[
0
].
iov_len
=
signlen
;
req
->
tx_iovlen
+=
1
;
req
->
tx_totallen
+=
signlen
;
server
->
tx
.
creq
=
req
;
__ncptcp_try_send
(
server
);
}
static
inline
void
__ncp_start_request
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
req
)
{
if
(
server
->
ncp_sock
->
type
==
SOCK_STREAM
)
ncptcp_start_request
(
server
,
req
);
else
ncpdgram_start_request
(
server
,
req
);
}
static
int
ncp_add_request
(
struct
ncp_server
*
server
,
struct
ncp_request_reply
*
req
)
{
down
(
&
server
->
rcv
.
creq_sem
);
if
(
!
ncp_conn_valid
(
server
))
{
up
(
&
server
->
rcv
.
creq_sem
);
printk
(
KERN_ERR
"ncpfs: tcp: Server died
\n
"
);
return
-
EIO
;
}
if
(
server
->
tx
.
creq
||
server
->
rcv
.
creq
)
{
req
->
status
=
RQ_QUEUED
;
list_add_tail
(
&
req
->
req
,
&
server
->
tx
.
requests
);
up
(
&
server
->
rcv
.
creq_sem
);
return
0
;
}
__ncp_start_request
(
server
,
req
);
up
(
&
server
->
rcv
.
creq_sem
);
return
0
;
}
static
void
__ncp_next_request
(
struct
ncp_server
*
server
)
{
struct
ncp_request_reply
*
req
;
server
->
rcv
.
creq
=
NULL
;
if
(
list_empty
(
&
server
->
tx
.
requests
))
{
return
;
}
req
=
list_entry
(
server
->
tx
.
requests
.
next
,
struct
ncp_request_reply
,
req
);
list_del_init
(
&
req
->
req
);
__ncp_start_request
(
server
,
req
);
}
static
void
__ncpdgram_rcv_proc
(
void
*
s
)
{
struct
ncp_server
*
server
=
s
;
struct
socket
*
sock
;
sock
=
server
->
ncp_sock
;
while
(
1
)
{
struct
ncp_reply_header
reply
;
int
result
;
result
=
_recv
(
sock
,
(
void
*
)
&
reply
,
sizeof
(
reply
),
MSG_PEEK
|
MSG_DONTWAIT
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
printk
(
KERN_ERR
"ncp_rpc_call: send error = %d
\n
"
,
result
);
break
;
return
result
;
}
}
re_select:
if
(
result
>=
sizeof
(
reply
))
{
poll_initwait
(
&
wait_table
);
struct
ncp_request_reply
*
req
;
/* mb() is not necessary because ->poll() will serialize
instructions adding the wait_table waitqueues in the
if
(
reply
.
type
==
NCP_WATCHDOG
)
{
waitqueue-head before going to calculate the mask-retval. */
unsigned
char
buf
[
10
];
__set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
!
(
sock
->
ops
->
poll
(
file
,
sock
,
&
wait_table
)
&
POLLIN
))
{
if
(
server
->
connection
!=
get_conn_number
(
&
reply
))
{
int
timed_out
;
goto
drop
;
if
(
timeout
>
max_timeout
)
{
/* JEJB/JSP 2/7/94
* This is useful to see if the system is
* hanging */
if
(
acknowledge_seen
==
0
)
{
printk
(
KERN_WARNING
"NCP max timeout
\n
"
);
}
}
timeout
=
max_timeout
;
result
=
_recv
(
sock
,
buf
,
sizeof
(
buf
),
MSG_DONTWAIT
);
}
if
(
result
<
0
)
{
timed_out
=
!
schedule_timeout
(
timeout
);
DPRINTK
(
"recv failed with %d
\n
"
,
result
);
poll_freewait
(
&
wait_table
);
current
->
state
=
TASK_RUNNING
;
if
(
signal_pending
(
current
))
{
result
=
-
ERESTARTSYS
;
break
;
}
if
(
wait_table
.
error
)
{
result
=
wait_table
.
error
;
break
;
}
if
(
timed_out
)
{
if
(
n
<
retrans
)
continue
;
continue
;
if
(
server
->
m
.
flags
&
NCP_MOUNT_SOFT
)
{
printk
(
KERN_WARNING
"NCP server not responding
\n
"
);
result
=
-
EIO
;
break
;
}
}
n
=
0
;
if
(
result
<
10
)
{
timeout
=
init_timeout
;
DPRINTK
(
"too short (%u) watchdog packet
\n
"
,
result
);
if
(
init_timeout
<
max_timeout
)
continue
;
init_timeout
<<=
1
;
}
if
(
!
major_timeout_seen
)
{
if
(
buf
[
9
]
!=
'?'
)
{
printk
(
KERN_WARNING
"NCP server not responding
\n
"
);
DPRINTK
(
"bad signature (%02X) in watchdog packet
\n
"
,
buf
[
9
]);
continue
;
}
}
major_timeout_seen
=
1
;
buf
[
9
]
=
'Y'
;
_send
(
sock
,
buf
,
sizeof
(
buf
));
continue
;
continue
;
}
}
}
else
{
down
(
&
server
->
rcv
.
creq_sem
);
poll_freewait
(
&
wait_table
);
req
=
server
->
rcv
.
creq
;
if
(
req
&&
(
req
->
tx_type
==
NCP_ALLOC_SLOT_REQUEST
||
(
server
->
sequence
==
reply
.
sequence
&&
server
->
connection
==
get_conn_number
(
&
reply
))))
{
if
(
reply
.
type
==
NCP_POSITIVE_ACK
)
{
server
->
timeout_retries
=
server
->
m
.
retry_count
;
server
->
timeout_last
=
NCP_MAX_RPC_TIMEOUT
;
mod_timer
(
&
server
->
timeout_tm
,
jiffies
+
NCP_MAX_RPC_TIMEOUT
);
}
else
if
(
reply
.
type
==
NCP_REPLY
)
{
result
=
_recv
(
sock
,
(
void
*
)
req
->
reply_buf
,
req
->
datalen
,
MSG_DONTWAIT
);
#ifdef CONFIG_NCPFS_PACKET_SIGNING
if
(
result
>=
0
&&
server
->
sign_active
&&
req
->
tx_type
!=
NCP_DEALLOC_SLOT_REQUEST
)
{
if
(
result
<
8
+
8
)
{
result
=
-
EIO
;
}
else
{
result
-=
8
;
}
}
#endif
del_timer
(
&
server
->
timeout_tm
);
server
->
rcv
.
creq
=
NULL
;
ncp_finish_request
(
req
,
result
);
__ncp_next_request
(
server
);
up
(
&
server
->
rcv
.
creq_sem
);
continue
;
}
}
up
(
&
server
->
rcv
.
creq_sem
);
}
}
current
->
state
=
TASK_RUNNING
;
drop:
;
_recv
(
sock
,
(
void
*
)
&
reply
,
sizeof
(
reply
),
MSG_DONTWAIT
);
}
}
/* Get the header from the next packet using a peek, so keep it
void
ncpdgram_rcv_proc
(
void
*
s
)
{
* on the recv queue. If it is wrong, it will be some reply
mm_segment_t
fs
;
* we don't now need, so discard it */
struct
ncp_server
*
server
=
s
;
result
=
_recv
(
sock
,
(
void
*
)
&
reply
,
sizeof
(
reply
),
MSG_PEEK
|
MSG_DONTWAIT
);
fs
=
get_fs
();
if
(
result
<
0
)
{
set_fs
(
get_ds
());
if
(
result
==
-
EAGAIN
)
{
__ncpdgram_rcv_proc
(
server
);
DDPRINTK
(
"ncp_rpc_call: bad select ready
\n
"
);
set_fs
(
fs
);
goto
re_select
;
}
}
if
(
result
==
-
ECONNREFUSED
)
{
static
void
__ncpdgram_timeout_proc
(
struct
ncp_server
*
server
)
{
DPRINTK
(
"ncp_rpc_call: server playing coy
\n
"
);
/* If timer is pending, we are processing another request... */
goto
re_select
;
if
(
!
timer_pending
(
&
server
->
timeout_tm
))
{
struct
ncp_request_reply
*
req
;
req
=
server
->
rcv
.
creq
;
if
(
req
)
{
int
timeout
;
if
(
server
->
m
.
flags
&
NCP_MOUNT_SOFT
)
{
if
(
server
->
timeout_retries
--
==
0
)
{
__ncp_abort_request
(
server
,
req
,
-
ETIMEDOUT
);
return
;
}
}
}
if
(
result
!=
-
ERESTARTSYS
)
{
/* Ignore errors */
printk
(
KERN_ERR
"ncp_rpc_call: recv error = %d
\n
"
,
ncpdgram_send
(
server
->
ncp_sock
,
req
);
-
result
);
timeout
=
server
->
timeout_last
<<
1
;
if
(
timeout
>
NCP_MAX_RPC_TIMEOUT
)
{
timeout
=
NCP_MAX_RPC_TIMEOUT
;
}
}
break
;
server
->
timeout_last
=
timeout
;
}
mod_timer
(
&
server
->
timeout_tm
,
jiffies
+
timeout
);
if
((
result
==
sizeof
(
reply
))
&&
(
reply
.
type
==
NCP_POSITIVE_ACK
))
{
/* Throw away the packet */
DPRINTK
(
"ncp_rpc_call: got positive acknowledge
\n
"
);
_recv
(
sock
,
(
void
*
)
&
reply
,
sizeof
(
reply
),
MSG_DONTWAIT
);
n
=
0
;
timeout
=
max_timeout
;
acknowledge_seen
=
1
;
goto
re_select
;
}
}
DDPRINTK
(
"ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
"seq: %d
\n
"
,
reply
.
type
,
(
reply
.
conn_high
<<
8
)
+
reply
.
conn_low
,
reply
.
task
,
reply
.
sequence
);
if
((
result
>=
sizeof
(
reply
))
&&
(
reply
.
type
==
NCP_REPLY
)
&&
((
request
.
type
==
NCP_ALLOC_SLOT_REQUEST
)
||
((
reply
.
sequence
==
request
.
sequence
)
&&
(
reply
.
conn_low
==
request
.
conn_low
)
/* seem to get wrong task from NW311 && (reply.task == request.task) */
&&
(
reply
.
conn_high
==
request
.
conn_high
))))
{
if
(
major_timeout_seen
)
printk
(
KERN_NOTICE
"NCP server OK
\n
"
);
break
;
}
/* JEJB/JSP 2/7/94
* we have xid mismatch, so discard the packet and start
* again. What a hack! but I can't call recvfrom with
* a null buffer yet. */
_recv
(
sock
,
(
void
*
)
&
reply
,
sizeof
(
reply
),
MSG_DONTWAIT
);
DPRINTK
(
"ncp_rpc_call: reply mismatch
\n
"
);
goto
re_select
;
}
/*
* we have the correct reply, so read into the correct place and
* return it
*/
result
=
_recv
(
sock
,
(
void
*
)
reply_buf
,
max_reply_size
,
MSG_DONTWAIT
);
if
(
result
<
0
)
{
printk
(
KERN_WARNING
"NCP: notice message: result=%d
\n
"
,
result
);
}
else
if
(
result
<
sizeof
(
struct
ncp_reply_header
))
{
printk
(
KERN_ERR
"NCP: just caught a too small read memory size..., "
"email to NET channel
\n
"
);
printk
(
KERN_ERR
"NCP: result=%d
\n
"
,
result
);
result
=
-
EIO
;
}
}
}
return
result
;
void
ncpdgram_timeout_proc
(
void
*
s
)
{
mm_segment_t
fs
;
struct
ncp_server
*
server
=
s
;
fs
=
get_fs
();
set_fs
(
get_ds
());
down
(
&
server
->
rcv
.
creq_sem
);
__ncpdgram_timeout_proc
(
server
);
up
(
&
server
->
rcv
.
creq_sem
);
set_fs
(
fs
);
}
static
inline
void
ncp_init_req
(
struct
ncp_request_reply
*
req
)
{
init_waitqueue_head
(
&
req
->
wq
);
req
->
status
=
RQ_IDLE
;
}
}
static
int
do_tcp_rcv
(
struct
ncp_server
*
server
,
void
*
buffer
,
size_t
len
)
{
static
int
do_tcp_rcv
(
struct
ncp_server
*
server
,
void
*
buffer
,
size_t
len
)
{
poll_table
wait_table
;
int
result
;
struct
file
*
file
;
struct
socket
*
sock
;
int
init_timeout
;
size_t
dataread
;
int
result
=
0
;
file
=
server
->
ncp_filp
;
sock
=
SOCKET_I
(
file
->
f_dentry
->
d_inode
);
dataread
=
0
;
if
(
buffer
)
{
result
=
_recv
(
server
->
ncp_sock
,
buffer
,
len
,
MSG_DONTWAIT
);
}
else
{
static
unsigned
char
dummy
[
1024
];
if
(
len
>
sizeof
(
dummy
))
{
len
=
sizeof
(
dummy
);
}
result
=
_recv
(
server
->
ncp_sock
,
dummy
,
len
,
MSG_DONTWAIT
);
}
if
(
result
<
0
)
{
return
result
;
}
if
(
result
>
len
)
{
printk
(
KERN_ERR
"ncpfs: tcp: bug in recvmsg (%u > %u)
\n
"
,
result
,
len
);
return
-
EIO
;
}
return
result
;
}
init_timeout
=
server
->
m
.
time_out
*
20
;
static
int
__ncptcp_rcv_proc
(
struct
ncp_server
*
server
)
{
/* We have to check the result, so store the complete header */
/* hard-mounted volumes have no timeout, except connection close... */
while
(
1
)
{
if
(
!
(
server
->
m
.
flags
&
NCP_MOUNT_SOFT
))
int
result
;
init_timeout
=
0x7FFF0000
;
struct
ncp_request_reply
*
req
;
int
datalen
;
while
(
len
)
{
int
type
;
poll_initwait
(
&
wait_table
);
/* mb() is not necessary because ->poll() will serialize
while
(
server
->
rcv
.
len
)
{
instructions adding the wait_table waitqueues in the
result
=
do_tcp_rcv
(
server
,
server
->
rcv
.
ptr
,
server
->
rcv
.
len
);
waitqueue-head before going to calculate the mask-retval. */
if
(
result
==
-
EAGAIN
)
{
__set_current_state
(
TASK_INTERRUPTIBLE
);
return
0
;
if
(
!
(
sock
->
ops
->
poll
(
file
,
sock
,
&
wait_table
)
&
POLLIN
))
{
init_timeout
=
schedule_timeout
(
init_timeout
);
poll_freewait
(
&
wait_table
);
current
->
state
=
TASK_RUNNING
;
if
(
signal_pending
(
current
))
{
return
-
ERESTARTSYS
;
}
}
if
(
!
init_timeout
)
{
if
(
result
<=
0
)
{
req
=
server
->
rcv
.
creq
;
if
(
req
)
{
__ncp_abort_request
(
server
,
req
,
-
EIO
);
}
else
{
__ncptcp_abort
(
server
);
}
if
(
result
<
0
)
{
printk
(
KERN_ERR
"ncpfs: tcp: error in recvmsg: %d
\n
"
,
result
);
}
else
{
DPRINTK
(
KERN_ERR
"ncpfs: tcp: EOF
\n
"
);
}
return
-
EIO
;
return
-
EIO
;
}
}
if
(
wait_table
.
erro
r
)
{
if
(
server
->
rcv
.
pt
r
)
{
return
wait_table
.
error
;
server
->
rcv
.
ptr
+=
result
;
}
}
}
else
{
server
->
rcv
.
len
-=
result
;
poll_freewait
(
&
wait_table
);
}
current
->
state
=
TASK_RUNNING
;
result
=
_recv
(
sock
,
buffer
,
len
,
MSG_DONTWAIT
);
if
(
result
<
0
)
{
if
(
result
==
-
EAGAIN
)
{
DDPRINTK
(
"ncpfs: tcp: bad select ready
\n
"
);
continue
;
}
return
result
;
}
if
(
result
==
0
)
{
printk
(
KERN_ERR
"ncpfs: tcp: EOF on socket
\n
"
);
return
-
EIO
;
}
}
if
(
result
>
len
)
{
switch
(
server
->
rcv
.
state
)
{
printk
(
KERN_ERR
"ncpfs: tcp: bug in recvmsg
\n
"
);
case
0
:
return
-
EIO
;
if
(
server
->
rcv
.
buf
.
magic
!=
htonl
(
NCP_TCP_RCVD_MAGIC
))
{
printk
(
KERN_ERR
"ncpfs: tcp: Unexpected reply type %08X
\n
"
,
ntohl
(
server
->
rcv
.
buf
.
magic
));
__ncptcp_abort
(
server
);
return
-
EIO
;
}
datalen
=
ntohl
(
server
->
rcv
.
buf
.
len
)
&
0x0FFFFFFF
;
if
(
datalen
<
10
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Unexpected reply len %d
\n
"
,
datalen
);
__ncptcp_abort
(
server
);
return
-
EIO
;
}
#ifdef CONFIG_NCPFS_PACKET_SIGNING
if
(
server
->
sign_active
)
{
if
(
datalen
<
18
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Unexpected reply len %d
\n
"
,
datalen
);
__ncptcp_abort
(
server
);
return
-
EIO
;
}
server
->
rcv
.
buf
.
len
=
datalen
-
8
;
server
->
rcv
.
ptr
=
(
unsigned
char
*
)
&
server
->
rcv
.
buf
.
p1
;
server
->
rcv
.
len
=
8
;
server
->
rcv
.
state
=
4
;
break
;
}
#endif
type
=
ntohs
(
server
->
rcv
.
buf
.
type
);
cont:
;
if
(
type
!=
NCP_REPLY
)
{
DPRINTK
(
"ncpfs: tcp: Unexpected NCP type %02X
\n
"
,
type
);
skipdata2:
;
server
->
rcv
.
state
=
2
;
skipdata:
;
server
->
rcv
.
ptr
=
NULL
;
server
->
rcv
.
len
=
datalen
-
10
;
break
;
}
req
=
server
->
rcv
.
creq
;
if
(
!
req
)
{
DPRINTK
(
KERN_ERR
"ncpfs: Reply without appropriate request
\n
"
);
goto
skipdata2
;
}
if
(
datalen
>
req
->
datalen
+
8
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Unexpected reply len %d (expected at most %d)
\n
"
,
datalen
,
req
->
datalen
+
8
);
server
->
rcv
.
state
=
3
;
goto
skipdata
;
}
req
->
datalen
=
datalen
-
8
;
req
->
reply_buf
->
type
=
NCP_REPLY
;
server
->
rcv
.
ptr
=
(
unsigned
char
*
)(
req
->
reply_buf
)
+
2
;
server
->
rcv
.
len
=
datalen
-
10
;
server
->
rcv
.
state
=
1
;
break
;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
case
4
:
datalen
=
server
->
rcv
.
buf
.
len
;
type
=
ntohs
(
server
->
rcv
.
buf
.
type2
);
goto
cont
;
#endif
case
1
:
req
=
server
->
rcv
.
creq
;
if
(
req
->
tx_type
!=
NCP_ALLOC_SLOT_REQUEST
)
{
if
(
req
->
reply_buf
->
sequence
!=
server
->
sequence
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Bad sequence number
\n
"
);
__ncp_abort_request
(
server
,
req
,
-
EIO
);
return
-
EIO
;
}
if
((
req
->
reply_buf
->
conn_low
|
(
req
->
reply_buf
->
conn_high
<<
8
))
!=
server
->
connection
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Connection number mismatch
\n
"
);
__ncp_abort_request
(
server
,
req
,
-
EIO
);
return
-
EIO
;
}
}
ncp_finish_request
(
req
,
req
->
datalen
);
nextreq:
;
__ncp_next_request
(
server
);
case
2
:
server
->
rcv
.
ptr
=
(
unsigned
char
*
)
&
server
->
rcv
.
buf
;
server
->
rcv
.
len
=
10
;
server
->
rcv
.
state
=
0
;
break
;
case
3
:
ncp_finish_request
(
server
->
rcv
.
creq
,
-
EIO
);
goto
nextreq
;
}
}
dataread
+=
result
;
buffer
+=
result
;
len
-=
result
;
}
}
return
0
;
}
}
#define NCP_TCP_XMIT_MAGIC (0x446D6454)
void
ncp_tcp_rcv_proc
(
void
*
s
)
{
#define NCP_TCP_XMIT_VERSION (1)
mm_segment_t
fs
;
#define NCP_TCP_RCVD_MAGIC (0x744E6350)
struct
ncp_server
*
server
=
s
;
fs
=
get_fs
();
set_fs
(
get_ds
());
down
(
&
server
->
rcv
.
creq_sem
);
__ncptcp_rcv_proc
(
server
);
up
(
&
server
->
rcv
.
creq_sem
);
set_fs
(
fs
);
return
;
}
static
int
do_ncp_tcp_rpc_call
(
struct
ncp_server
*
server
,
int
size
,
void
ncp_tcp_tx_proc
(
void
*
s
)
{
mm_segment_t
fs
;
struct
ncp_server
*
server
=
s
;
fs
=
get_fs
();
set_fs
(
get_ds
());
down
(
&
server
->
rcv
.
creq_sem
);
__ncptcp_try_send
(
server
);
up
(
&
server
->
rcv
.
creq_sem
);
set_fs
(
fs
);
return
;
}
static
int
do_ncp_rpc_call
(
struct
ncp_server
*
server
,
int
size
,
struct
ncp_reply_header
*
reply_buf
,
int
max_reply_size
)
struct
ncp_reply_header
*
reply_buf
,
int
max_reply_size
)
{
{
struct
file
*
file
;
struct
socket
*
sock
;
int
result
;
int
result
;
struct
iovec
iov
[
2
];
struct
ncp_request_reply
req
;
struct
msghdr
msg
;
struct
scm_cookie
scm
;
ncp_init_req
(
&
req
);
__u32
ncptcp_rcvd_hdr
[
2
];
req
.
reply_buf
=
reply_buf
;
__u32
ncptcp_xmit_hdr
[
4
];
req
.
datalen
=
max_reply_size
;
int
datalen
;
req
.
tx_iov
[
1
].
iov_base
=
(
void
*
)
server
->
packet
;
req
.
tx_iov
[
1
].
iov_len
=
size
;
/* We have to check the result, so store the complete header */
req
.
tx_iovlen
=
1
;
struct
ncp_request_header
request
=
req
.
tx_totallen
=
size
;
*
((
struct
ncp_request_header
*
)
(
server
->
packet
));
req
.
tx_type
=
*
(
u_int16_t
*
)
server
->
packet
;
file
=
server
->
ncp_filp
;
result
=
ncp_add_request
(
server
,
&
req
);
sock
=
SOCKET_I
(
file
->
f_dentry
->
d_inode
);
ncptcp_xmit_hdr
[
0
]
=
htonl
(
NCP_TCP_XMIT_MAGIC
);
ncptcp_xmit_hdr
[
1
]
=
htonl
(
size
+
16
);
ncptcp_xmit_hdr
[
2
]
=
htonl
(
NCP_TCP_XMIT_VERSION
);
ncptcp_xmit_hdr
[
3
]
=
htonl
(
max_reply_size
+
8
);
DDPRINTK
(
"ncpfs: req.typ: %04X, con: %d, "
"seq: %d"
,
request
.
type
,
(
request
.
conn_high
<<
8
)
+
request
.
conn_low
,
request
.
sequence
);
DDPRINTK
(
" func: %d
\n
"
,
request
.
function
);
iov
[
1
].
iov_base
=
(
void
*
)
server
->
packet
;
iov
[
1
].
iov_len
=
size
;
iov
[
0
].
iov_base
=
ncptcp_xmit_hdr
;
iov
[
0
].
iov_len
=
16
;
msg
.
msg_name
=
NULL
;
msg
.
msg_namelen
=
0
;
msg
.
msg_control
=
NULL
;
msg
.
msg_iov
=
iov
;
msg
.
msg_iovlen
=
2
;
msg
.
msg_flags
=
MSG_NOSIGNAL
;
result
=
scm_send
(
sock
,
&
msg
,
&
scm
);
if
(
result
<
0
)
{
return
result
;
}
result
=
sock
->
ops
->
sendmsg
(
sock
,
&
msg
,
size
+
16
,
&
scm
);
scm_destroy
(
&
scm
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Send failed: %d
\n
"
,
result
);
return
result
;
return
result
;
}
}
rstrcv:
if
(
wait_event_interruptible
(
req
.
wq
,
req
.
status
==
RQ_DONE
))
{
result
=
do_tcp_rcv
(
server
,
ncptcp_rcvd_hdr
,
8
);
ncp_abort_request
(
server
,
&
req
,
-
EIO
);
if
(
result
)
return
result
;
if
(
ncptcp_rcvd_hdr
[
0
]
!=
htonl
(
NCP_TCP_RCVD_MAGIC
))
{
printk
(
KERN_ERR
"ncpfs: tcp: Unexpected reply type %08X
\n
"
,
ntohl
(
ncptcp_rcvd_hdr
[
0
]));
return
-
EIO
;
}
}
datalen
=
ntohl
(
ncptcp_rcvd_hdr
[
1
]);
return
req
.
result
;
if
(
datalen
<
8
+
sizeof
(
*
reply_buf
)
||
datalen
>
max_reply_size
+
8
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Unexpected reply len %d
\n
"
,
datalen
);
return
-
EIO
;
}
datalen
-=
8
;
result
=
do_tcp_rcv
(
server
,
reply_buf
,
datalen
);
if
(
result
)
return
result
;
if
(
reply_buf
->
type
!=
NCP_REPLY
)
{
DDPRINTK
(
"ncpfs: tcp: Unexpected NCP type %02X
\n
"
,
reply_buf
->
type
);
goto
rstrcv
;
}
if
(
request
.
type
==
NCP_ALLOC_SLOT_REQUEST
)
return
datalen
;
if
(
reply_buf
->
sequence
!=
request
.
sequence
)
{
printk
(
KERN_ERR
"ncpfs: tcp: Bad sequence number
\n
"
);
return
-
EIO
;
}
if
((
reply_buf
->
conn_low
!=
request
.
conn_low
)
||
(
reply_buf
->
conn_high
!=
request
.
conn_high
))
{
printk
(
KERN_ERR
"ncpfs: tcp: Connection number mismatch
\n
"
);
return
-
EIO
;
}
return
datalen
;
}
}
/*
/*
...
@@ -426,8 +666,6 @@ static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size,
...
@@ -426,8 +666,6 @@ static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size,
static
int
ncp_do_request
(
struct
ncp_server
*
server
,
int
size
,
static
int
ncp_do_request
(
struct
ncp_server
*
server
,
int
size
,
void
*
reply
,
int
max_reply_size
)
void
*
reply
,
int
max_reply_size
)
{
{
struct
file
*
file
;
struct
socket
*
sock
;
int
result
;
int
result
;
if
(
server
->
lock
==
0
)
{
if
(
server
->
lock
==
0
)
{
...
@@ -435,21 +673,10 @@ static int ncp_do_request(struct ncp_server *server, int size,
...
@@ -435,21 +673,10 @@ static int ncp_do_request(struct ncp_server *server, int size,
return
-
EIO
;
return
-
EIO
;
}
}
if
(
!
ncp_conn_valid
(
server
))
{
if
(
!
ncp_conn_valid
(
server
))
{
printk
(
KERN_ERR
"ncpfs: Connection invalid!
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
#ifdef CONFIG_NCPFS_PACKET_SIGNING
if
(
server
->
sign_active
)
{
{
sign_packet
(
server
,
&
size
);
}
#endif
/* CONFIG_NCPFS_PACKET_SIGNING */
file
=
server
->
ncp_filp
;
sock
=
SOCKET_I
(
file
->
f_dentry
->
d_inode
);
/* N.B. this isn't needed ... check socket type? */
if
(
!
sock
)
{
printk
(
KERN_ERR
"ncp_rpc_call: socki_lookup failed
\n
"
);
result
=
-
EBADF
;
}
else
{
mm_segment_t
fs
;
mm_segment_t
fs
;
sigset_t
old_set
;
sigset_t
old_set
;
unsigned
long
mask
,
flags
;
unsigned
long
mask
,
flags
;
...
@@ -478,10 +705,7 @@ static int ncp_do_request(struct ncp_server *server, int size,
...
@@ -478,10 +705,7 @@ static int ncp_do_request(struct ncp_server *server, int size,
fs
=
get_fs
();
fs
=
get_fs
();
set_fs
(
get_ds
());
set_fs
(
get_ds
());
if
(
sock
->
type
==
SOCK_STREAM
)
result
=
do_ncp_rpc_call
(
server
,
size
,
reply
,
max_reply_size
);
result
=
do_ncp_tcp_rpc_call
(
server
,
size
,
reply
,
max_reply_size
);
else
result
=
do_ncp_rpc_call
(
server
,
size
,
reply
,
max_reply_size
);
set_fs
(
fs
);
set_fs
(
fs
);
...
@@ -510,20 +734,13 @@ int ncp_request2(struct ncp_server *server, int function,
...
@@ -510,20 +734,13 @@ int ncp_request2(struct ncp_server *server, int function,
{
{
struct
ncp_request_header
*
h
;
struct
ncp_request_header
*
h
;
struct
ncp_reply_header
*
reply
=
rpl
;
struct
ncp_reply_header
*
reply
=
rpl
;
int
request_size
=
server
->
current_size
-
sizeof
(
struct
ncp_request_header
);
int
result
;
int
result
;
h
=
(
struct
ncp_request_header
*
)
(
server
->
packet
);
h
=
(
struct
ncp_request_header
*
)
(
server
->
packet
);
if
(
server
->
has_subfunction
!=
0
)
{
if
(
server
->
has_subfunction
!=
0
)
{
*
(
__u16
*
)
&
(
h
->
data
[
0
])
=
htons
(
request_size
-
2
);
*
(
__u16
*
)
&
(
h
->
data
[
0
])
=
htons
(
server
->
current_size
-
sizeof
(
*
h
)
-
2
);
}
}
h
->
type
=
NCP_REQUEST
;
h
->
type
=
NCP_REQUEST
;
server
->
sequence
+=
1
;
h
->
sequence
=
server
->
sequence
;
h
->
conn_low
=
(
server
->
connection
)
&
0xff
;
h
->
conn_high
=
((
server
->
connection
)
&
0xff00
)
>>
8
;
/*
/*
* The server shouldn't know or care what task is making a
* The server shouldn't know or care what task is making a
* request, so we always use the same task number.
* request, so we always use the same task number.
...
@@ -531,7 +748,7 @@ int ncp_request2(struct ncp_server *server, int function,
...
@@ -531,7 +748,7 @@ int ncp_request2(struct ncp_server *server, int function,
h
->
task
=
2
;
/* (current->pid) & 0xff; */
h
->
task
=
2
;
/* (current->pid) & 0xff; */
h
->
function
=
function
;
h
->
function
=
function
;
result
=
ncp_do_request
(
server
,
request_size
+
sizeof
(
*
h
)
,
reply
,
size
);
result
=
ncp_do_request
(
server
,
server
->
current_size
,
reply
,
size
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
DPRINTK
(
"ncp_request_error: %d
\n
"
,
result
);
DPRINTK
(
"ncp_request_error: %d
\n
"
,
result
);
goto
out
;
goto
out
;
...
@@ -554,20 +771,17 @@ int ncp_connect(struct ncp_server *server)
...
@@ -554,20 +771,17 @@ int ncp_connect(struct ncp_server *server)
struct
ncp_request_header
*
h
;
struct
ncp_request_header
*
h
;
int
result
;
int
result
;
server
->
connection
=
0xFFFF
;
server
->
sequence
=
255
;
h
=
(
struct
ncp_request_header
*
)
(
server
->
packet
);
h
=
(
struct
ncp_request_header
*
)
(
server
->
packet
);
h
->
type
=
NCP_ALLOC_SLOT_REQUEST
;
h
->
type
=
NCP_ALLOC_SLOT_REQUEST
;
server
->
sequence
=
0
;
h
->
sequence
=
server
->
sequence
;
h
->
conn_low
=
0xff
;
h
->
conn_high
=
0xff
;
h
->
task
=
2
;
/* see above */
h
->
task
=
2
;
/* see above */
h
->
function
=
0
;
h
->
function
=
0
;
result
=
ncp_do_request
(
server
,
sizeof
(
*
h
),
server
->
packet
,
server
->
packet_size
);
result
=
ncp_do_request
(
server
,
sizeof
(
*
h
),
server
->
packet
,
server
->
packet_size
);
if
(
result
<
0
)
if
(
result
<
0
)
goto
out
;
goto
out
;
server
->
sequence
=
0
;
server
->
connection
=
h
->
conn_low
+
(
h
->
conn_high
*
256
);
server
->
connection
=
h
->
conn_low
+
(
h
->
conn_high
*
256
);
result
=
0
;
result
=
0
;
out:
out:
...
@@ -580,11 +794,6 @@ int ncp_disconnect(struct ncp_server *server)
...
@@ -580,11 +794,6 @@ int ncp_disconnect(struct ncp_server *server)
h
=
(
struct
ncp_request_header
*
)
(
server
->
packet
);
h
=
(
struct
ncp_request_header
*
)
(
server
->
packet
);
h
->
type
=
NCP_DEALLOC_SLOT_REQUEST
;
h
->
type
=
NCP_DEALLOC_SLOT_REQUEST
;
server
->
sequence
+=
1
;
h
->
sequence
=
server
->
sequence
;
h
->
conn_low
=
(
server
->
connection
)
&
0xff
;
h
->
conn_high
=
((
server
->
connection
)
&
0xff00
)
>>
8
;
h
->
task
=
2
;
/* see above */
h
->
task
=
2
;
/* see above */
h
->
function
=
0
;
h
->
function
=
0
;
...
...
include/linux/ncp.h
View file @
32758c3b
...
@@ -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
{
...
...
include/linux/ncp_fs_sb.h
View file @
32758c3b
...
@@ -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))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment