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>
19 #include <linux/netdevice.h>
20 #include <linux/workqueue.h>
22 #include <net/tcp_states.h>
25 #include <asm/uaccess.h>
26 #include <asm/ioctls.h>
31 #include "smb_debug.h"
37 _recvfrom(struct socket
*socket
, unsigned char *ubuf
, int size
, unsigned flags
)
39 struct kvec iov
= {ubuf
, size
};
40 struct msghdr msg
= {.msg_flags
= flags
};
41 msg
.msg_flags
|= MSG_DONTWAIT
| MSG_NOSIGNAL
;
42 return kernel_recvmsg(socket
, &msg
, &iov
, 1, size
, msg
.msg_flags
);
46 * Return the server this socket belongs to
48 static struct smb_sb_info
*
49 server_from_socket(struct socket
*socket
)
51 return socket
->sk
->sk_user_data
;
55 * Called when there is data on the socket.
58 smb_data_ready(struct sock
*sk
, int len
)
60 struct smb_sb_info
*server
= server_from_socket(sk
->sk_socket
);
61 void (*data_ready
)(struct sock
*, int) = server
->data_ready
;
64 VERBOSE("(%p, %d)\n", sk
, len
);
69 smb_valid_socket(struct inode
* inode
)
71 return (inode
&& S_ISSOCK(inode
->i_mode
) &&
72 SOCKET_I(inode
)->type
== SOCK_STREAM
);
75 static struct socket
*
76 server_sock(struct smb_sb_info
*server
)
80 if (server
&& (file
= server
->sock_file
))
83 if (!smb_valid_socket(file
->f_path
.dentry
->d_inode
))
84 PARANOIA("bad socket!\n");
86 return SOCKET_I(file
->f_path
.dentry
->d_inode
);
92 smb_close_socket(struct smb_sb_info
*server
)
94 struct file
* file
= server
->sock_file
;
97 struct socket
*sock
= server_sock(server
);
99 VERBOSE("closing socket %p\n", sock
);
100 sock
->sk
->sk_data_ready
= server
->data_ready
;
101 server
->sock_file
= NULL
;
107 smb_get_length(struct socket
*socket
, unsigned char *header
)
111 result
= _recvfrom(socket
, header
, 4, MSG_PEEK
);
112 if (result
== -EAGAIN
)
115 PARANOIA("recv error = %d\n", -result
);
127 DEBUG1("Got SESSION KEEP ALIVE\n");
128 _recvfrom(socket
, header
, 4, 0); /* read away */
132 PARANOIA("Invalid NBT packet, code=%x\n", header
[0]);
136 /* The length in the RFC NB header is the raw data length */
137 return smb_len(header
);
141 smb_recv_available(struct smb_sb_info
*server
)
145 struct socket
*sock
= server_sock(server
);
149 err
= sock
->ops
->ioctl(sock
, SIOCINQ
, (unsigned long) &avail
);
151 return (err
>= 0) ? avail
: err
;
155 * Adjust the kvec to move on 'n' bytes (from nfs/sunrpc)
158 smb_move_iov(struct kvec
**data
, size_t *num
, struct kvec
*vec
, unsigned amount
)
160 struct kvec
*iv
= *data
;
167 while (iv
->iov_len
<= amount
) {
168 amount
-= iv
->iov_len
;
174 * And chew down the partial one
176 vec
[0].iov_len
= iv
->iov_len
-amount
;
177 vec
[0].iov_base
=((unsigned char *)iv
->iov_base
)+amount
;
180 len
= vec
[0].iov_len
;
183 * And copy any others
185 for (i
= 1; i
< *num
; i
++) {
187 len
+= vec
[i
].iov_len
;
196 * Only called by the smbiod thread.
199 smb_receive_header(struct smb_sb_info
*server
)
203 unsigned char peek_buf
[4];
206 sock
= server_sock(server
);
209 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
212 if (!server
->smb_read
) {
213 result
= smb_get_length(sock
, peek_buf
);
215 if (result
== -ENODATA
)
219 server
->smb_len
= result
+ 4;
221 if (server
->smb_len
< SMB_HEADER_LEN
) {
222 PARANOIA("short packet: %d\n", result
);
223 server
->rstate
= SMB_RECV_DROP
;
227 if (server
->smb_len
> SMB_MAX_PACKET_SIZE
) {
228 PARANOIA("long packet: %d\n", result
);
229 server
->rstate
= SMB_RECV_DROP
;
235 result
= _recvfrom(sock
, server
->header
+ server
->smb_read
,
236 SMB_HEADER_LEN
- server
->smb_read
, 0);
237 VERBOSE("_recvfrom: %d\n", result
);
239 VERBOSE("receive error: %d\n", result
);
242 server
->smb_read
+= result
;
244 if (server
->smb_read
== SMB_HEADER_LEN
)
245 server
->rstate
= SMB_RECV_HCOMPLETE
;
250 static char drop_buffer
[PAGE_SIZE
];
253 * smb_receive_drop - read and throw away the data
254 * Only called by the smbiod thread.
256 * FIXME: we are in the kernel, could we just tell the socket that we want
257 * to drop stuff from the buffer?
260 smb_receive_drop(struct smb_sb_info
*server
)
266 int rlen
= smb_len(server
->header
) - server
->smb_read
+ 4;
269 if (rlen
> PAGE_SIZE
)
272 sock
= server_sock(server
);
275 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
278 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;
279 iov
.iov_base
= drop_buffer
;
280 iov
.iov_len
= PAGE_SIZE
;
281 msg
.msg_flags
= flags
;
284 msg
.msg_control
= NULL
;
286 result
= kernel_recvmsg(sock
, &msg
, &iov
, 1, rlen
, flags
);
288 VERBOSE("read: %d\n", result
);
290 VERBOSE("receive error: %d\n", result
);
293 server
->smb_read
+= result
;
295 if (server
->smb_read
>= server
->smb_len
)
296 server
->rstate
= SMB_RECV_END
;
304 * Only called by the smbiod thread.
307 smb_receive(struct smb_sb_info
*server
, struct smb_request
*req
)
312 struct kvec
*p
= req
->rq_iov
;
313 size_t num
= req
->rq_iovlen
;
318 sock
= server_sock(server
);
321 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
324 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;
325 msg
.msg_flags
= flags
;
328 msg
.msg_control
= NULL
;
330 /* Dont repeat bytes and count available bufferspace */
331 rlen
= min_t(int, smb_move_iov(&p
, &num
, iov
, req
->rq_bytes_recvd
),
332 (req
->rq_rlen
- req
->rq_bytes_recvd
));
334 result
= kernel_recvmsg(sock
, &msg
, p
, num
, rlen
, flags
);
336 VERBOSE("read: %d\n", result
);
338 VERBOSE("receive error: %d\n", result
);
341 req
->rq_bytes_recvd
+= result
;
342 server
->smb_read
+= result
;
349 * Try to send a SMB request. This may return after sending only parts of the
350 * request. SMB_REQ_TRANSMITTED will be set if a request was fully sent.
352 * Parts of this was taken from xprt_sendmsg from net/sunrpc/xprt.c
355 smb_send_request(struct smb_request
*req
)
357 struct smb_sb_info
*server
= req
->rq_server
;
359 struct msghdr msg
= {.msg_flags
= MSG_NOSIGNAL
| MSG_DONTWAIT
};
360 int slen
= req
->rq_slen
- req
->rq_bytes_sent
;
363 struct kvec
*p
= req
->rq_iov
;
364 size_t num
= req
->rq_iovlen
;
366 sock
= server_sock(server
);
369 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
372 /* Dont repeat bytes */
373 if (req
->rq_bytes_sent
)
374 smb_move_iov(&p
, &num
, iov
, req
->rq_bytes_sent
);
376 result
= kernel_sendmsg(sock
, &msg
, p
, num
, slen
);
379 req
->rq_bytes_sent
+= result
;
380 if (req
->rq_bytes_sent
>= req
->rq_slen
)
381 req
->rq_flags
|= SMB_REQ_TRANSMITTED
;