4 * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5 * Copyright (C) 1997 by Volker Lendecke
7 * Please add a note about your changes to smbfs in the ChangeLog file.
11 #include <linux/time.h>
12 #include <linux/errno.h>
13 #include <linux/socket.h>
14 #include <linux/fcntl.h>
15 #include <linux/file.h>
17 #include <linux/net.h>
18 #include <linux/tcp.h>
20 #include <linux/netdevice.h>
21 #include <linux/smp_lock.h>
22 #include <linux/workqueue.h>
23 #include <linux/net.h>
27 #include <linux/smb_fs.h>
28 #include <linux/smb.h>
29 #include <linux/smbno.h>
31 #include <asm/uaccess.h>
32 #include <asm/ioctls.h>
34 #include "smb_debug.h"
40 _recvfrom(struct socket
*socket
, unsigned char *ubuf
, int size
, unsigned flags
)
48 flags
|= MSG_DONTWAIT
| MSG_NOSIGNAL
;
50 msg
.msg_flags
= flags
;
55 msg
.msg_control
= NULL
;
59 size
= sock_recvmsg(socket
, &msg
, size
, flags
);
66 * Return the server this socket belongs to
68 static struct smb_sb_info
*
69 server_from_socket(struct socket
*socket
)
71 return socket
->sk
->sk_user_data
;
75 * Called when there is data on the socket.
78 smb_data_ready(struct sock
*sk
, int len
)
80 struct smb_sb_info
*server
= server_from_socket(sk
->sk_socket
);
81 void (*data_ready
)(struct sock
*, int) = server
->data_ready
;
84 VERBOSE("(%p, %d)\n", sk
, len
);
89 smb_valid_socket(struct inode
* inode
)
91 return (inode
&& S_ISSOCK(inode
->i_mode
) &&
92 SOCKET_I(inode
)->type
== SOCK_STREAM
);
95 static struct socket
*
96 server_sock(struct smb_sb_info
*server
)
100 if (server
&& (file
= server
->sock_file
))
102 #ifdef SMBFS_PARANOIA
103 if (!smb_valid_socket(file
->f_dentry
->d_inode
))
104 PARANOIA("bad socket!\n");
106 return SOCKET_I(file
->f_dentry
->d_inode
);
112 smb_close_socket(struct smb_sb_info
*server
)
114 struct file
* file
= server
->sock_file
;
117 struct socket
*sock
= server_sock(server
);
119 VERBOSE("closing socket %p\n", sock
);
120 sock
->sk
->sk_data_ready
= server
->data_ready
;
121 server
->sock_file
= NULL
;
127 smb_get_length(struct socket
*socket
, unsigned char *header
)
131 result
= _recvfrom(socket
, header
, 4, MSG_PEEK
);
132 if (result
== -EAGAIN
)
135 PARANOIA("recv error = %d\n", -result
);
147 DEBUG1("Got SESSION KEEP ALIVE\n");
148 _recvfrom(socket
, header
, 4, 0); /* read away */
152 PARANOIA("Invalid NBT packet, code=%x\n", header
[0]);
156 /* The length in the RFC NB header is the raw data length */
157 return smb_len(header
);
161 smb_recv_available(struct smb_sb_info
*server
)
165 struct socket
*sock
= server_sock(server
);
169 err
= sock
->ops
->ioctl(sock
, SIOCINQ
, (unsigned long) &avail
);
171 return (err
>= 0) ? avail
: err
;
175 * Adjust the iovec to move on 'n' bytes (from nfs/sunrpc)
178 smb_move_iov(struct msghdr
*msg
, struct iovec
*niv
, unsigned amount
)
180 struct iovec
*iv
= msg
->msg_iov
;
185 * Eat any sent iovecs
187 while (iv
->iov_len
<= amount
) {
188 amount
-= iv
->iov_len
;
194 * And chew down the partial one
196 niv
[0].iov_len
= iv
->iov_len
-amount
;
197 niv
[0].iov_base
=((unsigned char *)iv
->iov_base
)+amount
;
200 len
= niv
[0].iov_len
;
203 * And copy any others
205 for (i
= 1; i
< msg
->msg_iovlen
; i
++) {
207 len
+= niv
[i
].iov_len
;
216 * Only called by the smbiod thread.
219 smb_receive_header(struct smb_sb_info
*server
)
223 unsigned char peek_buf
[4];
226 sock
= server_sock(server
);
229 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
232 if (!server
->smb_read
) {
233 result
= smb_get_length(sock
, peek_buf
);
235 if (result
== -ENODATA
)
239 server
->smb_len
= result
+ 4;
241 if (server
->smb_len
< SMB_HEADER_LEN
) {
242 PARANOIA("short packet: %d\n", result
);
243 server
->rstate
= SMB_RECV_DROP
;
247 if (server
->smb_len
> SMB_MAX_PACKET_SIZE
) {
248 PARANOIA("long packet: %d\n", result
);
249 server
->rstate
= SMB_RECV_DROP
;
255 result
= _recvfrom(sock
, server
->header
+ server
->smb_read
,
256 SMB_HEADER_LEN
- server
->smb_read
, 0);
257 VERBOSE("_recvfrom: %d\n", result
);
259 VERBOSE("receive error: %d\n", result
);
262 server
->smb_read
+= result
;
264 if (server
->smb_read
== SMB_HEADER_LEN
)
265 server
->rstate
= SMB_RECV_HCOMPLETE
;
270 static char drop_buffer
[PAGE_SIZE
];
273 * smb_receive_drop - read and throw away the data
274 * Only called by the smbiod thread.
276 * FIXME: we are in the kernel, could we just tell the socket that we want
277 * to drop stuff from the buffer?
280 smb_receive_drop(struct smb_sb_info
*server
)
287 int rlen
= smb_len(server
->header
) - server
->smb_read
+ 4;
290 sock
= server_sock(server
);
293 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
299 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;
300 iov
.iov_base
= drop_buffer
;
301 iov
.iov_len
= PAGE_SIZE
;
302 msg
.msg_flags
= flags
;
307 msg
.msg_control
= NULL
;
309 if (rlen
> PAGE_SIZE
)
312 result
= sock_recvmsg(sock
, &msg
, rlen
, flags
);
316 VERBOSE("read: %d\n", result
);
318 VERBOSE("receive error: %d\n", result
);
321 server
->smb_read
+= result
;
323 if (server
->smb_read
>= server
->smb_len
)
324 server
->rstate
= SMB_RECV_END
;
332 * Only called by the smbiod thread.
335 smb_receive(struct smb_sb_info
*server
, struct smb_request
*req
)
345 sock
= server_sock(server
);
348 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
354 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;;
355 msg
.msg_flags
= flags
;
358 msg
.msg_iov
= req
->rq_iov
;
359 msg
.msg_iovlen
= req
->rq_iovlen
;
360 msg
.msg_control
= NULL
;
362 /* Dont repeat bytes and count available bufferspace */
363 rlen
= smb_move_iov(&msg
, iov
, req
->rq_bytes_recvd
);
364 if (req
->rq_rlen
< rlen
)
367 result
= sock_recvmsg(sock
, &msg
, rlen
, flags
);
371 VERBOSE("read: %d\n", result
);
373 VERBOSE("receive error: %d\n", result
);
376 req
->rq_bytes_recvd
+= result
;
377 server
->smb_read
+= result
;
384 * Try to send a SMB request. This may return after sending only parts of the
385 * request. SMB_REQ_TRANSMITTED will be set if a request was fully sent.
387 * Parts of this was taken from xprt_sendmsg from net/sunrpc/xprt.c
390 smb_send_request(struct smb_request
*req
)
393 struct smb_sb_info
*server
= req
->rq_server
;
396 int slen
= req
->rq_slen
- req
->rq_bytes_sent
;
400 sock
= server_sock(server
);
403 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
408 msg
.msg_control
= NULL
;
409 msg
.msg_controllen
= 0;
410 msg
.msg_iov
= req
->rq_iov
;
411 msg
.msg_iovlen
= req
->rq_iovlen
;
412 msg
.msg_flags
= MSG_NOSIGNAL
| MSG_DONTWAIT
;
414 /* Dont repeat bytes */
415 if (req
->rq_bytes_sent
)
416 smb_move_iov(&msg
, iov
, req
->rq_bytes_sent
);
420 result
= sock_sendmsg(sock
, &msg
, slen
);
424 req
->rq_bytes_sent
+= result
;
425 if (req
->rq_bytes_sent
>= req
->rq_slen
)
426 req
->rq_flags
|= SMB_REQ_TRANSMITTED
;