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 <linux/smb_fs.h>
26 #include <linux/smb.h>
27 #include <linux/smbno.h>
29 #include <asm/uaccess.h>
30 #include <asm/ioctls.h>
32 #include "smb_debug.h"
38 _recvfrom(struct socket
*socket
, unsigned char *ubuf
, int size
, unsigned flags
)
40 struct kvec iov
= {ubuf
, size
};
41 struct msghdr msg
= {.msg_flags
= flags
};
42 msg
.msg_flags
|= MSG_DONTWAIT
| MSG_NOSIGNAL
;
43 return kernel_recvmsg(socket
, &msg
, &iov
, 1, size
, msg
.msg_flags
);
47 * Return the server this socket belongs to
49 static struct smb_sb_info
*
50 server_from_socket(struct socket
*socket
)
52 return socket
->sk
->sk_user_data
;
56 * Called when there is data on the socket.
59 smb_data_ready(struct sock
*sk
, int len
)
61 struct smb_sb_info
*server
= server_from_socket(sk
->sk_socket
);
62 void (*data_ready
)(struct sock
*, int) = server
->data_ready
;
65 VERBOSE("(%p, %d)\n", sk
, len
);
70 smb_valid_socket(struct inode
* inode
)
72 return (inode
&& S_ISSOCK(inode
->i_mode
) &&
73 SOCKET_I(inode
)->type
== SOCK_STREAM
);
76 static struct socket
*
77 server_sock(struct smb_sb_info
*server
)
81 if (server
&& (file
= server
->sock_file
))
84 if (!smb_valid_socket(file
->f_path
.dentry
->d_inode
))
85 PARANOIA("bad socket!\n");
87 return SOCKET_I(file
->f_path
.dentry
->d_inode
);
93 smb_close_socket(struct smb_sb_info
*server
)
95 struct file
* file
= server
->sock_file
;
98 struct socket
*sock
= server_sock(server
);
100 VERBOSE("closing socket %p\n", sock
);
101 sock
->sk
->sk_data_ready
= server
->data_ready
;
102 server
->sock_file
= NULL
;
108 smb_get_length(struct socket
*socket
, unsigned char *header
)
112 result
= _recvfrom(socket
, header
, 4, MSG_PEEK
);
113 if (result
== -EAGAIN
)
116 PARANOIA("recv error = %d\n", -result
);
128 DEBUG1("Got SESSION KEEP ALIVE\n");
129 _recvfrom(socket
, header
, 4, 0); /* read away */
133 PARANOIA("Invalid NBT packet, code=%x\n", header
[0]);
137 /* The length in the RFC NB header is the raw data length */
138 return smb_len(header
);
142 smb_recv_available(struct smb_sb_info
*server
)
146 struct socket
*sock
= server_sock(server
);
150 err
= sock
->ops
->ioctl(sock
, SIOCINQ
, (unsigned long) &avail
);
152 return (err
>= 0) ? avail
: err
;
156 * Adjust the kvec to move on 'n' bytes (from nfs/sunrpc)
159 smb_move_iov(struct kvec
**data
, size_t *num
, struct kvec
*vec
, unsigned amount
)
161 struct kvec
*iv
= *data
;
168 while (iv
->iov_len
<= amount
) {
169 amount
-= iv
->iov_len
;
175 * And chew down the partial one
177 vec
[0].iov_len
= iv
->iov_len
-amount
;
178 vec
[0].iov_base
=((unsigned char *)iv
->iov_base
)+amount
;
181 len
= vec
[0].iov_len
;
184 * And copy any others
186 for (i
= 1; i
< *num
; i
++) {
188 len
+= vec
[i
].iov_len
;
197 * Only called by the smbiod thread.
200 smb_receive_header(struct smb_sb_info
*server
)
204 unsigned char peek_buf
[4];
207 sock
= server_sock(server
);
210 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
213 if (!server
->smb_read
) {
214 result
= smb_get_length(sock
, peek_buf
);
216 if (result
== -ENODATA
)
220 server
->smb_len
= result
+ 4;
222 if (server
->smb_len
< SMB_HEADER_LEN
) {
223 PARANOIA("short packet: %d\n", result
);
224 server
->rstate
= SMB_RECV_DROP
;
228 if (server
->smb_len
> SMB_MAX_PACKET_SIZE
) {
229 PARANOIA("long packet: %d\n", result
);
230 server
->rstate
= SMB_RECV_DROP
;
236 result
= _recvfrom(sock
, server
->header
+ server
->smb_read
,
237 SMB_HEADER_LEN
- server
->smb_read
, 0);
238 VERBOSE("_recvfrom: %d\n", result
);
240 VERBOSE("receive error: %d\n", result
);
243 server
->smb_read
+= result
;
245 if (server
->smb_read
== SMB_HEADER_LEN
)
246 server
->rstate
= SMB_RECV_HCOMPLETE
;
251 static char drop_buffer
[PAGE_SIZE
];
254 * smb_receive_drop - read and throw away the data
255 * Only called by the smbiod thread.
257 * FIXME: we are in the kernel, could we just tell the socket that we want
258 * to drop stuff from the buffer?
261 smb_receive_drop(struct smb_sb_info
*server
)
267 int rlen
= smb_len(server
->header
) - server
->smb_read
+ 4;
270 if (rlen
> PAGE_SIZE
)
273 sock
= server_sock(server
);
276 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
279 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;
280 iov
.iov_base
= drop_buffer
;
281 iov
.iov_len
= PAGE_SIZE
;
282 msg
.msg_flags
= flags
;
285 msg
.msg_control
= NULL
;
287 result
= kernel_recvmsg(sock
, &msg
, &iov
, 1, rlen
, flags
);
289 VERBOSE("read: %d\n", result
);
291 VERBOSE("receive error: %d\n", result
);
294 server
->smb_read
+= result
;
296 if (server
->smb_read
>= server
->smb_len
)
297 server
->rstate
= SMB_RECV_END
;
305 * Only called by the smbiod thread.
308 smb_receive(struct smb_sb_info
*server
, struct smb_request
*req
)
313 struct kvec
*p
= req
->rq_iov
;
314 size_t num
= req
->rq_iovlen
;
319 sock
= server_sock(server
);
322 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
325 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;
326 msg
.msg_flags
= flags
;
329 msg
.msg_control
= NULL
;
331 /* Dont repeat bytes and count available bufferspace */
332 rlen
= min_t(int, smb_move_iov(&p
, &num
, iov
, req
->rq_bytes_recvd
),
333 (req
->rq_rlen
- req
->rq_bytes_recvd
));
335 result
= kernel_recvmsg(sock
, &msg
, p
, num
, rlen
, flags
);
337 VERBOSE("read: %d\n", result
);
339 VERBOSE("receive error: %d\n", result
);
342 req
->rq_bytes_recvd
+= result
;
343 server
->smb_read
+= result
;
350 * Try to send a SMB request. This may return after sending only parts of the
351 * request. SMB_REQ_TRANSMITTED will be set if a request was fully sent.
353 * Parts of this was taken from xprt_sendmsg from net/sunrpc/xprt.c
356 smb_send_request(struct smb_request
*req
)
358 struct smb_sb_info
*server
= req
->rq_server
;
360 struct msghdr msg
= {.msg_flags
= MSG_NOSIGNAL
| MSG_DONTWAIT
};
361 int slen
= req
->rq_slen
- req
->rq_bytes_sent
;
364 struct kvec
*p
= req
->rq_iov
;
365 size_t num
= req
->rq_iovlen
;
367 sock
= server_sock(server
);
370 if (sock
->sk
->sk_state
!= TCP_ESTABLISHED
)
373 /* Dont repeat bytes */
374 if (req
->rq_bytes_sent
)
375 smb_move_iov(&p
, &num
, iov
, req
->rq_bytes_sent
);
377 result
= kernel_sendmsg(sock
, &msg
, p
, num
, slen
);
380 req
->rq_bytes_sent
+= result
;
381 if (req
->rq_bytes_sent
>= req
->rq_slen
)
382 req
->rq_flags
|= SMB_REQ_TRANSMITTED
;