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"
26 /*****************************************************************************/
29 fs points to the correct segment, sock != NULL, target != NULL
30 The smb header is only stored if want_header != 0. */
32 smb_receive_raw (const struct smb_server
*server
, int sock_fd
, unsigned char *target
, int max_raw_length
, int want_header
)
36 unsigned char netbios_session_buf
[256];
37 int netbios_session_payload_size
;
41 /* Read the NetBIOS session header (rfc-1002, section 4.3.1) */
42 result
= recvfrom (sock_fd
, netbios_session_buf
, 4, 0, NULL
, NULL
);
45 LOG (("smb_receive_raw: recv error = %ld\n", errno
));
52 LOG (("smb_receive_raw: got less than 4 bytes\n"));
57 netbios_session_payload_size
= (int)smb_len (netbios_session_buf
);
61 if(netbios_session_buf
[0] != 0x00 && netbios_session_payload_size
> 0)
63 if(netbios_session_payload_size
> 256 - 4)
64 netbios_session_payload_size
= 256 - 4;
66 result
= recvfrom (sock_fd
, &netbios_session_buf
[4], netbios_session_payload_size
- 4, 0, NULL
, NULL
);
69 LOG (("smb_receive_raw: recv error = %ld\n", errno
));
74 if(result
< netbios_session_payload_size
- 4)
80 dump_netbios_header(__FILE__
,__LINE__
,netbios_session_buf
,&netbios_session_buf
[4],netbios_session_payload_size
);
84 dump_netbios_header(__FILE__
,__LINE__
,netbios_session_buf
,NULL
,0);
87 #endif /* defined(DUMP_SMB) */
89 /* Check the session type. */
90 switch (netbios_session_buf
[0])
92 /* 0x00 == session message */
97 /* 0x85 == session keepalive */
100 LOG (("smb_receive_raw: Got SESSION KEEP ALIVE\n"));
103 /* 0x81 == session request */
104 /* 0x82 == positive session response */
105 /* 0x83 == negative session response */
106 /* 0x84 == retarget session response */
109 LOG (("smb_receive_raw: Invalid session header type 0x%02lx\n", netbios_session_buf
[0]));
114 /* The length in the RFC NB header is the raw data length (17 bits) */
115 len
= netbios_session_payload_size
;
116 if (len
> max_raw_length
)
118 LOG (("smb_receive_raw: Received length (%ld) > max_xmit (%ld)!\n", len
, max_raw_length
));
123 /* Prepend the NetBIOS header to what is read? */
126 /* Check for buffer overflow. */
127 if(len
+ 4 > max_raw_length
)
129 LOG (("smb_receive_raw: Received length (%ld) > max_xmit (%ld)!\n", len
, max_raw_length
));
134 memcpy (target
, netbios_session_buf
, 4);
138 for(already_read
= 0 ; already_read
< len
; already_read
+= result
)
140 result
= recvfrom (sock_fd
, (void *) (target
+ already_read
), len
- already_read
, 0, NULL
, NULL
);
143 LOG (("smb_receive_raw: recvfrom error = %ld\n", errno
));
151 #if defined(DUMP_SMB)
153 /* If want_header==0 then this is the data returned by SMB_COM_READ_RAW. */
154 dump_smb(__FILE__
,__LINE__
,!want_header
,target
,already_read
,smb_packet_to_consumer
,server
->max_recv
);
156 #endif /* defined(DUMP_SMB) */
158 result
= already_read
;
166 fs points to the correct segment, server != NULL, sock!=NULL */
168 smb_receive (struct smb_server
*server
, int sock_fd
)
170 byte
* packet
= server
->packet
;
173 result
= smb_receive_raw (server
, sock_fd
, packet
,
174 server
->max_recv
- 4, /* max_xmit in server includes NB header */
175 1); /* We want the header */
178 LOG (("smb_receive: receive error: %ld\n", result
));
182 server
->rcls
= *((unsigned char *) (packet
+ 9));
183 server
->err
= WVAL (packet
, 11);
185 if (server
->rcls
!= 0)
186 LOG (("smb_receive: rcls=%ld, err=%ld\n", server
->rcls
, server
->err
));
193 /* smb_receive's preconditions also apply here. */
195 smb_receive_trans2 (struct smb_server
*server
, int sock_fd
, int *data_len
, int *param_len
, char **data
, char **param
)
197 unsigned char *inbuf
= server
->packet
;
202 LOG (("smb_receive_trans2: enter\n"));
204 (*data_len
) = (*param_len
) = 0;
205 (*param
) = (*data
) = NULL
;
207 result
= smb_receive (server
, sock_fd
);
211 if (server
->rcls
!= 0)
214 /* parse out the lengths */
215 total_data
= WVAL (inbuf
, smb_tdrcnt
);
216 total_param
= WVAL (inbuf
, smb_tprcnt
);
218 if ((total_data
> server
->max_buffer_size
) || (total_param
> server
->max_buffer_size
))
220 LOG (("smb_receive_trans2: data/param too long\n"));
226 /* Allocate it, but only if there is something to allocate
227 in the first place. ZZZ this may not be the proper approach,
228 and we should return an error for 'no data'. */
231 (*data
) = malloc (total_data
);
234 LOG (("smb_receive_trans2: could not alloc data area\n"));
245 /* Allocate it, but only if there is something to allocate
246 in the first place. ZZZ this may not be the proper approach,
247 and we should return an error for 'no parameters'. */
250 (*param
) = malloc(total_param
);
251 if ((*param
) == NULL
)
253 LOG (("smb_receive_trans2: could not alloc param area\n"));
264 LOG (("smb_rec_trans2: total_data/param: %ld/%ld\n", total_data
, total_param
));
268 if (WVAL (inbuf
, smb_prdisp
) + WVAL (inbuf
, smb_prcnt
) > total_param
)
270 LOG (("smb_receive_trans2: invalid parameters\n"));
276 memcpy ((*param
) + WVAL (inbuf
, smb_prdisp
), smb_base (inbuf
) + WVAL (inbuf
, smb_proff
), WVAL (inbuf
, smb_prcnt
));
278 (*param_len
) += WVAL (inbuf
, smb_prcnt
);
280 if (WVAL (inbuf
, smb_drdisp
) + WVAL (inbuf
, smb_drcnt
) > total_data
)
282 LOG (("smb_receive_trans2: invalid data block\n"));
288 memcpy ((*data
) + WVAL (inbuf
, smb_drdisp
), smb_base (inbuf
) + WVAL (inbuf
, smb_droff
), WVAL (inbuf
, smb_drcnt
));
290 (*data_len
) += WVAL (inbuf
, smb_drcnt
);
292 LOG (("smb_rec_trans2: drcnt/prcnt: %ld/%ld\n", WVAL (inbuf
, smb_drcnt
), WVAL (inbuf
, smb_prcnt
)));
294 /* parse out the total lengths again - they can shrink! */
295 if ((WVAL (inbuf
, smb_tdrcnt
) > total_data
) || (WVAL (inbuf
, smb_tprcnt
) > total_param
))
297 LOG (("smb_receive_trans2: data/params grew!\n"));
302 total_data
= WVAL (inbuf
, smb_tdrcnt
);
303 total_param
= WVAL (inbuf
, smb_tprcnt
);
304 if (total_data
<= (*data_len
) && total_param
<= (*param_len
))
307 result
= smb_receive (server
, sock_fd
);
311 if (server
->rcls
!= 0)
313 /* smb_trans2_request() will check server->rcls, etc. and
314 * produce a matching error code value.
321 LOG (("smb_receive_trans2: normal exit\n"));
326 LOG (("smb_receive_trans2: failed exit\n"));
334 (*param
) = (*data
) = NULL
;
340 smb_release (struct smb_server
*server
)
344 if (server
->mount_data
.fd
>= 0)
345 CloseSocket (server
->mount_data
.fd
);
347 server
->mount_data
.fd
= socket (AF_INET
, SOCK_STREAM
, 0);
348 if (server
->mount_data
.fd
< 0)
362 smb_connect (struct smb_server
*server
)
364 int sock_fd
= server
->mount_data
.fd
;
373 result
= connect (sock_fd
, (struct sockaddr
*)&server
->mount_data
.addr
, sizeof(struct sockaddr_in
));
382 /*****************************************************************************
384 * This routine was once taken from nfs, which is for udp. Here TCP does
385 * most of the ugly stuff for us (thanks, Alan!)
387 ****************************************************************************/
389 /* Returns number of bytes received (>= 0) or a negative value in
393 smb_request (struct smb_server
*server
)
396 int sock_fd
= server
->mount_data
.fd
;
397 unsigned char *buffer
= server
->packet
;
399 if ((sock_fd
< 0) || (buffer
== NULL
))
401 LOG (("smb_request: Bad server!\n"));
406 if (server
->state
!= CONN_VALID
)
412 /* Length includes the NetBIOS session header (4 bytes), which
413 * is prepended to the packet to be sent.
415 len
= smb_len (buffer
) + 4;
417 LOG (("smb_request: len = %ld cmd = 0x%lx\n", len
, buffer
[8]));
419 #if defined(DUMP_SMB)
420 dump_netbios_header(__FILE__
,__LINE__
,buffer
,&buffer
[4],len
);
421 dump_smb(__FILE__
,__LINE__
,0,buffer
+4,len
-4,smb_packet_from_consumer
,server
->max_recv
);
422 #endif /* defined(DUMP_SMB) */
424 result
= send (sock_fd
, (void *) buffer
, len
, 0);
427 LOG (("smb_request: send error = %ld\n", errno
));
433 result
= smb_receive (server
, sock_fd
);
440 server
->state
= CONN_INVALID
;
441 smb_invalidate_all_inodes (server
);
444 LOG (("smb_request: result = %ld\n", result
));
449 /* This is not really a trans2 request, we assume that you only have
450 one packet to send. */
452 smb_trans2_request (struct smb_server
*server
, int *data_len
, int *param_len
, char **data
, char **param
)
455 int sock_fd
= server
->mount_data
.fd
;
456 unsigned char *buffer
= server
->packet
;
458 if (server
->state
!= CONN_VALID
)
464 /* Length includes the NetBIOS session header (4 bytes), which
465 * is prepended to the packet to be sent.
467 len
= smb_len (buffer
) + 4;
469 LOG (("smb_request: len = %ld cmd = 0x%02lx\n", len
, buffer
[8]));
471 #if defined(DUMP_SMB)
472 dump_netbios_header(__FILE__
,__LINE__
,buffer
,NULL
,0);
473 dump_smb(__FILE__
,__LINE__
,0,buffer
+4,len
-4,smb_packet_from_consumer
,server
->max_recv
);
474 #endif /* defined(DUMP_SMB) */
476 result
= send (sock_fd
, (void *) buffer
, len
, 0);
479 LOG (("smb_trans2_request: send error = %ld\n", errno
));
485 result
= smb_receive_trans2 (server
, sock_fd
, data_len
, param_len
, data
, param
);
492 server
->state
= CONN_INVALID
;
493 smb_invalidate_all_inodes (server
);
496 LOG (("smb_trans2_request: result = %ld\n", result
));
501 /* target must be in user space */
503 smb_request_read_raw (struct smb_server
*server
, unsigned char *target
, int max_len
)
506 int sock_fd
= server
->mount_data
.fd
;
507 unsigned char *buffer
= server
->packet
;
509 if (server
->state
!= CONN_VALID
)
515 /* Length includes the NetBIOS session header (4 bytes), which
516 * is prepended to the packet to be sent.
518 len
= smb_len (buffer
) + 4;
520 LOG (("smb_request_read_raw: len = %ld cmd = 0x%02lx\n", len
, buffer
[8]));
521 LOG (("smb_request_read_raw: target=%lx, max_len=%ld\n", (unsigned int) target
, max_len
));
522 LOG (("smb_request_read_raw: buffer=%lx, sock=%lx\n", (unsigned int) buffer
, (unsigned int) sock_fd
));
524 #if defined(DUMP_SMB)
525 dump_netbios_header(__FILE__
,__LINE__
,buffer
,NULL
,0);
526 dump_smb(__FILE__
,__LINE__
,0,buffer
+4,len
-4,smb_packet_from_consumer
,server
->max_recv
);
527 #endif /* defined(DUMP_SMB) */
529 /* Request that data should be read in raw mode. */
530 result
= send (sock_fd
, (void *) buffer
, len
, 0);
532 LOG (("smb_request_read_raw: send returned %ld\n", result
));
536 LOG (("smb_request_read_raw: send error = %ld\n", errno
));
542 /* Wait for the raw data to be sent by the server. */
543 result
= smb_receive_raw (server
, sock_fd
, target
, max_len
, 0);
550 server
->state
= CONN_INVALID
;
551 smb_invalidate_all_inodes (server
);
554 LOG (("smb_request_read_raw: result = %ld\n", result
));
559 /* Source must be in user space. smb_request_write_raw assumes that
560 the request SMBwriteBraw has been completed successfully, so that
561 we can send the raw data now. */
563 smb_request_write_raw (struct smb_server
*server
, unsigned const char *source
, int length
)
567 int sock_fd
= server
->mount_data
.fd
;
569 if (server
->state
!= CONN_VALID
)
575 /* Send the NetBIOS header. */
576 smb_encode_smb_length (nb_header
, length
);
578 result
= send (sock_fd
, (void *) nb_header
, 4, 0);
581 /* Now send the data to be written. */
582 result
= send (sock_fd
, (void *) source
, length
, 0);
594 LOG (("smb_request_write_raw: send returned %ld\n", result
));
596 /* If the write operation succeeded, wait for the
597 * server to confirm it.
599 if (result
== length
)
600 result
= smb_receive (server
, sock_fd
);
606 server
->state
= CONN_INVALID
;
608 smb_invalidate_all_inodes (server
);
614 LOG (("smb_request_write_raw: result = %ld\n", result
));