patch-1.3.21 linux/fs/smbfs/sock.c
Next file: linux/include/asm-i386/string.h
Previous file: linux/fs/smbfs/proc.c
Back to the patch index
Back to the overall index
- Lines: 366
- Date:
Mon Aug 28 09:48:36 1995
- Orig file:
v1.3.20/linux/fs/smbfs/sock.c
- Orig date:
Tue Jul 11 10:02:58 1995
diff -u --recursive --new-file v1.3.20/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c
@@ -175,27 +175,36 @@
}
/*
- * smb_receive
- * fs points to the correct segment, server != NULL, sock!=NULL
+ * smb_receive_raw
+ * fs points to the correct segment, sock != NULL, target != NULL
+ * The smb header is only stored if want_header != 0.
*/
static int
-smb_receive(struct smb_server *server, struct socket *sock)
+smb_receive_raw(struct socket *sock, unsigned char *target,
+ int max_raw_length, int want_header)
{
int len, result;
+ int already_read;
unsigned char peek_buf[4];
+ unsigned short fs; /* We fool the kernel to believe
+ we call from user space. */
+
re_recv:
+ fs = get_fs();
+ set_fs(get_ds());
result = sock->ops->recvfrom(sock, (void *)peek_buf, 4, 0,
- MSG_PEEK, NULL, NULL);
+ 0, NULL, NULL);
+ set_fs(fs);
if (result < 0) {
- DPRINTK("smb_receive: recv error = %d\n", -result);
+ DPRINTK("smb_receive_raw: recv error = %d\n", -result);
return result;
}
- if (result == 0) {
- DPRINTK("smb_receive: got 0 bytes\n");
+ if (result < 4) {
+ DPRINTK("smb_receive_raw: got less than 4 bytes\n");
return -EIO;
}
@@ -206,51 +215,72 @@
break;
case 0x85:
- DPRINTK("smb_receive: Got SESSION KEEP ALIVE\n");
- sock->ops->recvfrom(sock, (void *)peek_buf, 4, 1,
- 0, NULL, NULL);
+ DPRINTK("smb_receive_raw: Got SESSION KEEP ALIVE\n");
goto re_recv;
default:
- printk("smb_receive: Invalid packet\n");
+ printk("smb_receive_raw: Invalid packet\n");
return -EIO;
}
- /* Length not including first four bytes. */
- len = smb_len(peek_buf) + 4;
- if (len > server->max_xmit) {
- printk("smb_receive: Received length (%d) > max_xmit (%d)!\n",
- len, server->max_xmit);
+ /* The length in the RFC NB header is the raw data length */
+ len = smb_len(peek_buf);
+ if (len > max_raw_length) {
+ printk("smb_receive_raw: Received length (%d) > max_xmit (%d)!\n",
+ len, max_raw_length);
return -EIO;
}
- else
- {
- int already_read = 0;
- while (already_read < len) {
+ if (want_header != 0) {
+ memcpy_tofs(target, peek_buf, 4);
+ target += 4;
+ }
+
+ already_read = 0;
+
+ while (already_read < len) {
- result = sock->ops->
- recvfrom(sock,
- (void *)(server->packet+already_read),
- len - already_read, 0, 0,
- NULL, NULL);
+ result = sock->ops->
+ recvfrom(sock,
+ (void *)(target+already_read),
+ len - already_read, 0, 0,
+ NULL, NULL);
- if (result < 0) {
- printk("SMB: notice message: error = %d\n",
- -result);
- return result;
- }
-
- already_read += result;
+ if (result < 0) {
+ printk("smb_receive_raw: recvfrom error = %d\n",
+ -result);
+ return result;
}
- result = already_read;
+
+ already_read += result;
+ }
+ return already_read;
+}
+
+/*
+ * smb_receive
+ * fs points to the correct segment, server != NULL, sock!=NULL
+ */
+static int
+smb_receive(struct smb_server *server, struct socket *sock)
+{
+ int result;
+
+ result = smb_receive_raw(sock, server->packet,
+ server->max_xmit - 4, /* max_xmit in server
+ includes NB header */
+ 1); /* We want the header */
+
+ if (result < 0) {
+ printk("smb_receive: receive error: %d\n", result);
+ return result;
}
server->rcls = *((unsigned char *)(server->packet+9));
server->err = *((unsigned short *)(server->packet+11));
if (server->rcls != 0) {
- DPRINTK("smb_response: rcls=%d, err=%d\n",
+ DPRINTK("smb_receive: rcls=%d, err=%d\n",
server->rcls, server->err);
}
@@ -447,12 +477,6 @@
if (server->state != CONN_VALID)
return -EIO;
-#if 0
- while (server->lock)
- sleep_on(&server->wait);
- server->lock = 1;
-#endif
-
if ((result = smb_dont_catch_keepalive(server)) != 0) {
server->state = CONN_INVALID;
smb_invalidate_all_inodes(server);
@@ -486,11 +510,6 @@
result = result2;
}
-#if 0
- server->lock = 0;
- wake_up(&server->wait);
-#endif
-
if (result < 0) {
server->state = CONN_INVALID;
smb_invalidate_all_inodes(server);
@@ -526,12 +545,6 @@
if (server->state != CONN_VALID)
return -EIO;
-#if 0
- while (server->lock)
- sleep_on(&server->wait);
- server->lock = 1;
-#endif
-
if ((result = smb_dont_catch_keepalive(server)) != 0) {
server->state = CONN_INVALID;
smb_invalidate_all_inodes(server);
@@ -540,13 +553,13 @@
len = smb_len(buffer) + 4;
- DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
-
old_mask = current->blocked;
current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
fs = get_fs();
set_fs(get_ds());
+ DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
+
result = sock->ops->send(sock, (void *)buffer, len, 0, 0);
if (result < 0) {
printk("smb_trans2_request: send error = %d\n", result);
@@ -567,17 +580,162 @@
result = result2;
}
-#if 0
- server->lock = 0;
- wake_up(&server->wait);
-#endif
-
if (result < 0) {
server->state = CONN_INVALID;
smb_invalidate_all_inodes(server);
}
DDPRINTK("smb_trans2_request: result = %d\n", result);
+
+ return result;
+}
+
+/* target must be in user space */
+int
+smb_request_read_raw(struct smb_server *server,
+ unsigned char *target, int max_len)
+{
+ unsigned long old_mask;
+ int len, result, result2;
+ unsigned short fs; /* We fool the kernel to believe
+ we call from user space. */
+
+ struct socket *sock = server_sock(server);
+ unsigned char *buffer = (server == NULL) ? NULL : server->packet;
+
+ if ((sock == NULL) || (buffer == NULL)) {
+ printk("smb_request_read_raw: Bad server!\n");
+ return -EBADF;
+ }
+
+ if (server->state != CONN_VALID)
+ return -EIO;
+
+ if ((result = smb_dont_catch_keepalive(server)) != 0) {
+ server->state = CONN_INVALID;
+ smb_invalidate_all_inodes(server);
+ return result;
+ }
+
+ len = smb_len(buffer) + 4;
+
+ old_mask = current->blocked;
+ current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
+ fs = get_fs();
+ set_fs(get_ds());
+
+ DPRINTK("smb_request_read_raw: len = %d cmd = 0x%X\n",
+ len, buffer[8]);
+ DPRINTK("smb_request_read_raw: target=%X, max_len=%d\n",
+ (unsigned int)target, max_len);
+ DPRINTK("smb_request_read_raw: buffer=%X, sock=%X\n",
+ (unsigned int)buffer, (unsigned int)sock);
+
+ result = sock->ops->send(sock, (void *)buffer, len, 0, 0);
+
+ DPRINTK("smb_request_read_raw: send returned %d\n", result);
+
+ set_fs(fs); /* We recv into user space */
+
+ if (result < 0) {
+ printk("smb_request_read_raw: send error = %d\n", result);
+ }
+ else {
+ result = smb_receive_raw(sock, target, max_len, 0);
+ }
+
+ /* read/write errors are handled by errno */
+ current->signal &= ~_S(SIGPIPE);
+ current->blocked = old_mask;
+
+ if ((result2 = smb_catch_keepalive(server)) < 0) {
+ result = result2;
+ }
+
+ if (result < 0) {
+ server->state = CONN_INVALID;
+ smb_invalidate_all_inodes(server);
+ }
+
+ DPRINTK("smb_request_read_raw: result = %d\n", result);
+
+ return result;
+}
+
+/* Source must be in user space. smb_request_write_raw assumes that
+ * the request SMBwriteBraw has been completed successfully, so that
+ * we can send the raw data now. */
+int
+smb_request_write_raw(struct smb_server *server,
+ unsigned const char *source, int length)
+{
+ unsigned long old_mask;
+ int result, result2;
+ unsigned short fs; /* We fool the kernel to believe
+ we call from user space. */
+ byte nb_header[4];
+
+ struct socket *sock = server_sock(server);
+ unsigned char *buffer = (server == NULL) ? NULL : server->packet;
+
+ if ((sock == NULL) || (buffer == NULL)) {
+ printk("smb_request_write_raw: Bad server!\n");
+ return -EBADF;
+ }
+
+ if (server->state != CONN_VALID)
+ return -EIO;
+
+ if ((result = smb_dont_catch_keepalive(server)) != 0) {
+ server->state = CONN_INVALID;
+ smb_invalidate_all_inodes(server);
+ return result;
+ }
+
+ old_mask = current->blocked;
+ current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
+ fs = get_fs();
+ set_fs(get_ds());
+
+ smb_encode_smb_length(nb_header, length);
+
+ result = sock->ops->send(sock, (void *)nb_header, 4, 0, 0);
+
+ if (result == 4) {
+ set_fs(fs); /* source is in user-land */
+ result = sock->ops->send(sock, (void *)source, length, 0, 0);
+ set_fs(get_ds());
+ } else {
+ result = -EIO;
+ }
+
+ DPRINTK("smb_request_write_raw: send returned %d\n", result);
+
+ if (result == length) {
+ result = smb_receive(server, sock);
+ } else {
+ result = -EIO;
+ }
+
+ /* read/write errors are handled by errno */
+ current->signal &= ~_S(SIGPIPE);
+ current->blocked = old_mask;
+ set_fs(fs);
+
+ if ((result2 = smb_catch_keepalive(server)) < 0) {
+ result = result2;
+ }
+
+ if (result < 0) {
+ server->state = CONN_INVALID;
+ smb_invalidate_all_inodes(server);
+ }
+
+ if (result > 0) {
+ result = length;
+ }
+
+ DPRINTK("smb_request_write_raw: result = %d\n", result);
return result;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this