8 * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
9 * Modified by Christian Starkjohann <cs -at- hal -dot- kph -dot- tuwien -dot- ac -dot- at>
10 * Modified for use with AmigaOS by Olaf Barthel <obarthel -at- gmx -dot- net>
15 /*****************************************************************************/
17 #include <smb/smb_fs.h>
19 #include <smb/smbno.h>
21 /*****************************************************************************/
23 #include "smb_abstraction.h"
25 /*****************************************************************************/
28 fs points to the correct segment, sock != NULL, target != NULL
29 The smb header is only stored if want_header != 0. */
31 smb_receive_raw (int sock_fd
, unsigned char *target
, int max_raw_length
, int want_header
)
35 unsigned char peek_buf
[4];
39 result
= recvfrom (sock_fd
, (void *) peek_buf
, 4, 0, NULL
, NULL
);
42 LOG (("smb_receive_raw: recv error = %ld\n", errno
));
49 LOG (("smb_receive_raw: got less than 4 bytes\n"));
61 LOG (("smb_receive_raw: Got SESSION KEEP ALIVE\n"));
65 LOG (("smb_receive_raw: Invalid packet 0x%02lx\n", peek_buf
[0]));
70 /* The length in the RFC NB header is the raw data length */
71 len
= smb_len (peek_buf
);
72 if (len
> max_raw_length
)
74 LOG (("smb_receive_raw: Received length (%ld) > max_xmit (%ld)!\n", len
, max_raw_length
));
81 memcpy (target
, peek_buf
, 4);
87 while (already_read
< len
)
89 result
= recvfrom (sock_fd
, (void *) (target
+ already_read
), len
- already_read
, 0, NULL
, NULL
);
92 LOG (("smb_receive_raw: recvfrom error = %ld\n", errno
));
99 already_read
+= result
;
102 result
= already_read
;
110 fs points to the correct segment, server != NULL, sock!=NULL */
112 smb_receive (struct smb_server
*server
, int sock_fd
)
114 byte
* packet
= server
->packet
;
117 result
= smb_receive_raw (sock_fd
, packet
,
118 server
->max_recv
- 4, /* max_xmit in server includes NB header */
119 1); /* We want the header */
122 LOG (("smb_receive: receive error: %ld\n", result
));
126 server
->rcls
= *((unsigned char *) (packet
+ 9));
127 server
->err
= WVAL (packet
, 11);
129 if (server
->rcls
!= 0)
130 LOG (("smb_receive: rcls=%ld, err=%ld\n", server
->rcls
, server
->err
));
137 /* smb_receive's preconditions also apply here. */
139 smb_receive_trans2 (struct smb_server
*server
, int sock_fd
, int *data_len
, int *param_len
, char **data
, char **param
)
141 unsigned char *inbuf
= server
->packet
;
146 LOG (("smb_receive_trans2: enter\n"));
148 (*data_len
) = (*param_len
) = 0;
149 (*param
) = (*data
) = NULL
;
151 result
= smb_receive (server
, sock_fd
);
155 if (server
->rcls
!= 0)
158 /* parse out the lengths */
159 total_data
= WVAL (inbuf
, smb_tdrcnt
);
160 total_param
= WVAL (inbuf
, smb_tprcnt
);
162 if ((total_data
> server
->max_xmit
) || (total_param
> server
->max_xmit
))
164 LOG (("smb_receive_trans2: data/param too long\n"));
170 /* Allocate it, but only if there is something to allocate
171 in the first place. ZZZ this may not be the proper approach,
172 and we should return an error for 'no data'. */
175 (*data
) = malloc (total_data
);
178 LOG (("smb_receive_trans2: could not alloc data area\n"));
189 /* Allocate it, but only if there is something to allocate
190 in the first place. ZZZ this may not be the proper approach,
191 and we should return an error for 'no parameters'. */
194 (*param
) = malloc(total_param
);
195 if ((*param
) == NULL
)
197 LOG (("smb_receive_trans2: could not alloc param area\n"));
208 LOG (("smb_rec_trans2: total_data/param: %ld/%ld\n", total_data
, total_param
));
212 if (WVAL (inbuf
, smb_prdisp
) + WVAL (inbuf
, smb_prcnt
) > (unsigned int)total_param
)
214 LOG (("smb_receive_trans2: invalid parameters\n"));
220 memcpy ((*param
) + WVAL (inbuf
, smb_prdisp
), smb_base (inbuf
) + WVAL (inbuf
, smb_proff
), WVAL (inbuf
, smb_prcnt
));
222 (*param_len
) += WVAL (inbuf
, smb_prcnt
);
224 if (WVAL (inbuf
, smb_drdisp
) + WVAL (inbuf
, smb_drcnt
) > (unsigned int)total_data
)
226 LOG (("smb_receive_trans2: invalid data block\n"));
232 memcpy ((*data
) + WVAL (inbuf
, smb_drdisp
), smb_base (inbuf
) + WVAL (inbuf
, smb_droff
), WVAL (inbuf
, smb_drcnt
));
234 (*data_len
) += WVAL (inbuf
, smb_drcnt
);
236 LOG (("smb_rec_trans2: drcnt/prcnt: %ld/%ld\n", WVAL (inbuf
, smb_drcnt
), WVAL (inbuf
, smb_prcnt
)));
238 /* parse out the total lengths again - they can shrink! */
239 if ((WVAL (inbuf
, smb_tdrcnt
) > (unsigned int)total_data
) || (WVAL (inbuf
, smb_tprcnt
) > (unsigned int)total_param
))
241 LOG (("smb_receive_trans2: data/params grew!\n"));
246 total_data
= WVAL (inbuf
, smb_tdrcnt
);
247 total_param
= WVAL (inbuf
, smb_tprcnt
);
248 if (total_data
<= (*data_len
) && total_param
<= (*param_len
))
251 result
= smb_receive (server
, sock_fd
);
255 if (server
->rcls
!= 0)
262 LOG (("smb_receive_trans2: normal exit\n"));
267 LOG (("smb_receive_trans2: failed exit\n"));
275 (*param
) = (*data
) = NULL
;
281 smb_release (struct smb_server
*server
)
285 if (server
->mount_data
.fd
>= 0)
286 CloseSocket (server
->mount_data
.fd
);
288 server
->mount_data
.fd
= socket (AF_INET
, SOCK_STREAM
, 0);
289 if (server
->mount_data
.fd
< 0)
303 smb_connect (struct smb_server
*server
)
305 int sock_fd
= server
->mount_data
.fd
;
314 result
= connect (sock_fd
, (struct sockaddr
*)&server
->mount_data
.addr
, sizeof(struct sockaddr_in
));
323 /*****************************************************************************
325 * This routine was once taken from nfs, which is for udp. Here TCP does
326 * most of the ugly stuff for us (thanks, Alan!)
328 ****************************************************************************/
331 smb_request (struct smb_server
*server
)
334 int sock_fd
= server
->mount_data
.fd
;
335 unsigned char *buffer
= server
->packet
;
337 if ((sock_fd
< 0) || (buffer
== NULL
))
339 LOG (("smb_request: Bad server!\n"));
344 if (server
->state
!= CONN_VALID
)
350 len
= smb_len (buffer
) + 4;
352 LOG (("smb_request: len = %ld cmd = 0x%lx\n", len
, buffer
[8]));
354 result
= send (sock_fd
, (void *) buffer
, len
, 0);
357 LOG (("smb_request: send error = %ld\n", errno
));
363 result
= smb_receive (server
, sock_fd
);
370 server
->state
= CONN_INVALID
;
371 smb_invalidate_all_inodes (server
);
374 LOG (("smb_request: result = %ld\n", result
));
379 /* This is not really a trans2 request, we assume that you only have
380 one packet to send. */
382 smb_trans2_request (struct smb_server
*server
, int *data_len
, int *param_len
, char **data
, char **param
)
385 int sock_fd
= server
->mount_data
.fd
;
386 unsigned char *buffer
= server
->packet
;
388 if (server
->state
!= CONN_VALID
)
394 len
= smb_len (buffer
) + 4;
396 LOG (("smb_request: len = %ld cmd = 0x%02lx\n", len
, buffer
[8]));
398 result
= send (sock_fd
, (void *) buffer
, len
, 0);
401 LOG (("smb_trans2_request: send error = %ld\n", errno
));
407 result
= smb_receive_trans2 (server
, sock_fd
, data_len
, param_len
, data
, param
);
414 server
->state
= CONN_INVALID
;
415 smb_invalidate_all_inodes (server
);
418 LOG (("smb_trans2_request: result = %ld\n", result
));
423 /* target must be in user space */
425 smb_request_read_raw (struct smb_server
*server
, unsigned char *target
, int max_len
)
428 int sock_fd
= server
->mount_data
.fd
;
429 unsigned char *buffer
= server
->packet
;
431 if (server
->state
!= CONN_VALID
)
437 len
= smb_len (buffer
) + 4;
439 LOG (("smb_request_read_raw: len = %ld cmd = 0x%02lx\n", len
, buffer
[8]));
440 LOG (("smb_request_read_raw: target=%lx, max_len=%ld\n", (unsigned int) target
, max_len
));
441 LOG (("smb_request_read_raw: buffer=%lx, sock=%lx\n", (unsigned int) buffer
, (unsigned int) sock_fd
));
443 result
= send (sock_fd
, (void *) buffer
, len
, 0);
445 LOG (("smb_request_read_raw: send returned %ld\n", result
));
449 LOG (("smb_request_read_raw: send error = %ld\n", errno
));
455 result
= smb_receive_raw (sock_fd
, target
, max_len
, 0);
462 server
->state
= CONN_INVALID
;
463 smb_invalidate_all_inodes (server
);
466 LOG (("smb_request_read_raw: result = %ld\n", result
));
471 /* Source must be in user space. smb_request_write_raw assumes that
472 the request SMBwriteBraw has been completed successfully, so that
473 we can send the raw data now. */
475 smb_request_write_raw (struct smb_server
*server
, unsigned const char *source
, int length
)
479 int sock_fd
= server
->mount_data
.fd
;
481 if (server
->state
!= CONN_VALID
)
487 smb_encode_smb_length (nb_header
, length
);
489 result
= send (sock_fd
, (void *) nb_header
, 4, 0);
492 result
= send (sock_fd
, (void *) source
, length
, 0);
504 LOG (("smb_request_write_raw: send returned %ld\n", result
));
506 if (result
== length
)
507 result
= smb_receive (server
, sock_fd
);
513 server
->state
= CONN_INVALID
;
515 smb_invalidate_all_inodes (server
);
521 LOG (("smb_request_write_raw: result = %ld\n", result
));