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>
26 #include <linux/smb_fs.h>
27 #include <linux/smb.h>
28 #include <linux/smbno.h>
30 #include <asm/uaccess.h>
31 #include <asm/ioctls.h>
33 #include "smb_debug.h"
39 _recvfrom(struct socket
*socket
, unsigned char *ubuf
, int size
, unsigned flags
)
49 flags
|= MSG_DONTWAIT
| MSG_NOSIGNAL
;
51 msg
.msg_flags
= flags
;
56 msg
.msg_control
= NULL
;
60 init_sync_kiocb(&iocb
, NULL
);
61 si
= kiocb_to_siocb(&iocb
);
63 si
->scm
= &si
->async_scm
;
68 memset(si
->scm
, 0, sizeof(*si
->scm
));
70 size
= socket
->ops
->recvmsg(&iocb
, socket
, &msg
, size
, flags
, si
->scm
);
72 scm_recv(socket
, &msg
, si
->scm
, flags
);
73 if (-EIOCBQUEUED
== size
)
74 size
= wait_on_sync_kiocb(&iocb
);
81 * Return the server this socket belongs to
83 static struct smb_sb_info
*
84 server_from_socket(struct socket
*socket
)
86 return socket
->sk
->user_data
;
90 * Called when there is data on the socket.
93 smb_data_ready(struct sock
*sk
, int len
)
95 struct smb_sb_info
*server
= server_from_socket(sk
->socket
);
96 void (*data_ready
)(struct sock
*, int) = server
->data_ready
;
99 VERBOSE("(%p, %d)\n", sk
, len
);
104 smb_valid_socket(struct inode
* inode
)
106 return (inode
&& S_ISSOCK(inode
->i_mode
) &&
107 SOCKET_I(inode
)->type
== SOCK_STREAM
);
110 static struct socket
*
111 server_sock(struct smb_sb_info
*server
)
115 if (server
&& (file
= server
->sock_file
))
117 #ifdef SMBFS_PARANOIA
118 if (!smb_valid_socket(file
->f_dentry
->d_inode
))
119 PARANOIA("bad socket!\n");
121 return SOCKET_I(file
->f_dentry
->d_inode
);
127 smb_close_socket(struct smb_sb_info
*server
)
129 struct file
* file
= server
->sock_file
;
132 struct socket
*sock
= server_sock(server
);
134 VERBOSE("closing socket %p\n", sock
);
135 sock
->sk
->data_ready
= server
->data_ready
;
136 server
->sock_file
= NULL
;
142 smb_get_length(struct socket
*socket
, unsigned char *header
)
146 result
= _recvfrom(socket
, header
, 4, MSG_PEEK
);
147 if (result
== -EAGAIN
)
150 PARANOIA("recv error = %d\n", -result
);
162 DEBUG1("Got SESSION KEEP ALIVE\n");
163 _recvfrom(socket
, header
, 4, 0); /* read away */
167 PARANOIA("Invalid NBT packet, code=%x\n", header
[0]);
171 /* The length in the RFC NB header is the raw data length */
172 return smb_len(header
);
176 smb_recv_available(struct smb_sb_info
*server
)
180 struct socket
*sock
= server_sock(server
);
184 err
= sock
->ops
->ioctl(sock
, SIOCINQ
, (unsigned long) &avail
);
186 return (err
>= 0) ? avail
: err
;
190 * Adjust the iovec to move on 'n' bytes (from nfs/sunrpc)
193 smb_move_iov(struct msghdr
*msg
, struct iovec
*niv
, unsigned amount
)
195 struct iovec
*iv
= msg
->msg_iov
;
200 * Eat any sent iovecs
202 while (iv
->iov_len
<= amount
) {
203 amount
-= iv
->iov_len
;
209 * And chew down the partial one
211 niv
[0].iov_len
= iv
->iov_len
-amount
;
212 niv
[0].iov_base
=((unsigned char *)iv
->iov_base
)+amount
;
215 len
= niv
[0].iov_len
;
218 * And copy any others
220 for (i
= 1; i
< msg
->msg_iovlen
; i
++) {
222 len
+= niv
[i
].iov_len
;
231 * Only called by the smbiod thread.
234 smb_receive_header(struct smb_sb_info
*server
)
238 unsigned char peek_buf
[4];
241 sock
= server_sock(server
);
244 if (sock
->sk
->state
!= TCP_ESTABLISHED
)
247 if (!server
->smb_read
) {
248 result
= smb_get_length(sock
, peek_buf
);
250 if (result
== -ENODATA
)
254 server
->smb_len
= result
+ 4;
256 if (server
->smb_len
< SMB_HEADER_LEN
) {
257 PARANOIA("short packet: %d\n", result
);
258 server
->rstate
= SMB_RECV_DROP
;
262 if (server
->smb_len
> SMB_MAX_PACKET_SIZE
) {
263 PARANOIA("long packet: %d\n", result
);
264 server
->rstate
= SMB_RECV_DROP
;
270 result
= _recvfrom(sock
, server
->header
+ server
->smb_read
,
271 SMB_HEADER_LEN
- server
->smb_read
, 0);
272 VERBOSE("_recvfrom: %d\n", result
);
274 VERBOSE("receive error: %d\n", result
);
277 server
->smb_read
+= result
;
279 if (server
->smb_read
== SMB_HEADER_LEN
)
280 server
->rstate
= SMB_RECV_HCOMPLETE
;
285 static char drop_buffer
[PAGE_SIZE
];
288 * smb_receive_drop - read and throw away the data
289 * Only called by the smbiod thread.
291 * FIXME: we are in the kernel, could we just tell the socket that we want
292 * to drop stuff from the buffer?
295 smb_receive_drop(struct smb_sb_info
*server
)
302 struct sock_iocb
*si
;
304 int rlen
= smb_len(server
->header
) - server
->smb_read
+ 4;
307 sock
= server_sock(server
);
310 if (sock
->sk
->state
!= TCP_ESTABLISHED
)
316 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;
317 iov
.iov_base
= drop_buffer
;
318 iov
.iov_len
= PAGE_SIZE
;
319 msg
.msg_flags
= flags
;
324 msg
.msg_control
= NULL
;
326 if (rlen
> PAGE_SIZE
)
329 init_sync_kiocb(&iocb
, NULL
);
330 si
= kiocb_to_siocb(&iocb
);
332 si
->scm
= &si
->async_scm
;
337 memset(si
->scm
, 0, sizeof(*si
->scm
));
339 result
= sock
->ops
->recvmsg(&iocb
, sock
, &msg
, rlen
, flags
, si
->scm
);
341 scm_recv(sock
, &msg
, si
->scm
, flags
);
342 if (-EIOCBQUEUED
== result
)
343 result
= wait_on_sync_kiocb(&iocb
);
347 VERBOSE("read: %d\n", result
);
349 VERBOSE("receive error: %d\n", result
);
352 server
->smb_read
+= result
;
354 if (server
->smb_read
>= server
->smb_len
)
355 server
->rstate
= SMB_RECV_END
;
363 * Only called by the smbiod thread.
366 smb_receive(struct smb_sb_info
*server
, struct smb_request
*req
)
373 struct sock_iocb
*si
;
378 sock
= server_sock(server
);
381 if (sock
->sk
->state
!= TCP_ESTABLISHED
)
387 flags
= MSG_DONTWAIT
| MSG_NOSIGNAL
;;
388 msg
.msg_flags
= flags
;
391 msg
.msg_iov
= req
->rq_iov
;
392 msg
.msg_iovlen
= req
->rq_iovlen
;
393 msg
.msg_control
= NULL
;
395 /* Dont repeat bytes and count available bufferspace */
396 rlen
= smb_move_iov(&msg
, iov
, req
->rq_bytes_recvd
);
397 if (req
->rq_rlen
< rlen
)
400 init_sync_kiocb(&iocb
, NULL
);
401 si
= kiocb_to_siocb(&iocb
);
403 si
->scm
= &si
->async_scm
;
408 memset(si
->scm
, 0, sizeof(*si
->scm
));
410 result
= sock
->ops
->recvmsg(&iocb
, sock
, &msg
, rlen
, flags
, si
->scm
);
412 scm_recv(sock
, &msg
, si
->scm
, flags
);
413 if (-EIOCBQUEUED
== result
)
414 result
= wait_on_sync_kiocb(&iocb
);
418 VERBOSE("read: %d\n", result
);
420 VERBOSE("receive error: %d\n", result
);
423 req
->rq_bytes_recvd
+= result
;
424 server
->smb_read
+= result
;
431 * Try to send a SMB request. This may return after sending only parts of the
432 * request. SMB_REQ_TRANSMITTED will be set if a request was fully sent.
434 * Parts of this was taken from xprt_sendmsg from net/sunrpc/xprt.c
437 smb_send_request(struct smb_request
*req
)
440 struct smb_sb_info
*server
= req
->rq_server
;
443 struct sock_iocb
*si
;
445 int slen
= req
->rq_slen
- req
->rq_bytes_sent
;
449 sock
= server_sock(server
);
452 if (sock
->sk
->state
!= TCP_ESTABLISHED
)
457 msg
.msg_control
= NULL
;
458 msg
.msg_controllen
= 0;
459 msg
.msg_iov
= req
->rq_iov
;
460 msg
.msg_iovlen
= req
->rq_iovlen
;
461 msg
.msg_flags
= MSG_NOSIGNAL
| MSG_DONTWAIT
;
463 /* Dont repeat bytes */
464 if (req
->rq_bytes_sent
)
465 smb_move_iov(&msg
, iov
, req
->rq_bytes_sent
);
467 init_sync_kiocb(&iocb
, NULL
);
468 si
= kiocb_to_siocb(&iocb
);
469 si
->scm
= &si
->async_scm
;
476 result
= scm_send(sock
, &msg
, si
->scm
);
478 result
= sock
->ops
->sendmsg(&iocb
, sock
, &msg
, slen
, si
->scm
);
479 if (-EIOCBQUEUED
!= result
)
480 scm_destroy(si
->scm
);
482 if (-EIOCBQUEUED
== result
)
483 result
= wait_on_sync_kiocb(&iocb
);
487 req
->rq_bytes_sent
+= result
;
488 if (req
->rq_bytes_sent
>= req
->rq_slen
)
489 req
->rq_flags
|= SMB_REQ_TRANSMITTED
;