alsa.audio: build the bridge link lib only for linux architecture
[AROS.git] / workbench / network / smbfs / source_code / sock.c
blob1d3fc6ea67389c4e6ca6d66ea452e81c25ae46c5
1 /*
2 * $Id$
4 * :ts=8
6 * sock.c
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>
13 #include "smbfs.h"
15 /*****************************************************************************/
17 #include <smb/smb_fs.h>
18 #include <smb/smb.h>
19 #include <smb/smbno.h>
21 /*****************************************************************************/
23 #include "smb_abstraction.h"
25 /*****************************************************************************/
27 /* smb_receive_raw
28 fs points to the correct segment, sock != NULL, target != NULL
29 The smb header is only stored if want_header != 0. */
30 static int
31 smb_receive_raw (int sock_fd, unsigned char *target, int max_raw_length, int want_header)
33 int len, result;
34 int already_read;
35 unsigned char peek_buf[4];
37 re_recv:
39 result = recvfrom (sock_fd, (void *) peek_buf, 4, 0, NULL, NULL);
40 if (result < 0)
42 LOG (("smb_receive_raw: recv error = %ld\n", errno));
43 result = (-errno);
44 goto out;
47 if (result < 4)
49 LOG (("smb_receive_raw: got less than 4 bytes\n"));
50 result = -EIO;
51 goto out;
54 switch (peek_buf[0])
56 case 0x00:
57 case 0x82:
58 break;
60 case 0x85:
61 LOG (("smb_receive_raw: Got SESSION KEEP ALIVE\n"));
62 goto re_recv;
64 default:
65 LOG (("smb_receive_raw: Invalid packet 0x%02lx\n", peek_buf[0]));
66 result = -EIO;
67 goto out;
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));
75 result = -EIO;
76 goto out;
79 if (want_header != 0)
81 memcpy (target, peek_buf, 4);
82 target += 4;
85 already_read = 0;
87 while (already_read < len)
89 result = recvfrom (sock_fd, (void *) (target + already_read), len - already_read, 0, NULL, NULL);
90 if (result < 0)
92 LOG (("smb_receive_raw: recvfrom error = %ld\n", errno));
94 result = (-errno);
96 goto out;
99 already_read += result;
102 result = already_read;
104 out:
106 return result;
109 /* smb_receive
110 fs points to the correct segment, server != NULL, sock!=NULL */
111 static int
112 smb_receive (struct smb_server *server, int sock_fd)
114 byte * packet = server->packet;
115 int result;
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 */
120 if (result < 0)
122 LOG (("smb_receive: receive error: %ld\n", result));
123 goto out;
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));
132 out:
134 return result;
137 /* smb_receive's preconditions also apply here. */
138 static int
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;
142 int total_data;
143 int total_param;
144 int result;
146 LOG (("smb_receive_trans2: enter\n"));
148 (*data_len) = (*param_len) = 0;
149 (*param) = (*data) = NULL;
151 result = smb_receive (server, sock_fd);
152 if (result < 0)
153 goto fail;
155 if (server->rcls != 0)
156 goto fail;
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"));
166 result = -EIO;
167 goto fail;
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'. */
173 if(total_data > 0)
175 (*data) = malloc (total_data);
176 if ((*data) == NULL)
178 LOG (("smb_receive_trans2: could not alloc data area\n"));
180 result = -ENOMEM;
181 goto fail;
184 else
186 (*data) = NULL;
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'. */
192 if(total_param > 0)
194 (*param) = malloc(total_param);
195 if ((*param) == NULL)
197 LOG (("smb_receive_trans2: could not alloc param area\n"));
199 result = -ENOMEM;
200 goto fail;
203 else
205 (*param) = NULL;
208 LOG (("smb_rec_trans2: total_data/param: %ld/%ld\n", total_data, total_param));
210 while (1)
212 if (WVAL (inbuf, smb_prdisp) + WVAL (inbuf, smb_prcnt) > (unsigned int)total_param)
214 LOG (("smb_receive_trans2: invalid parameters\n"));
215 result = -EIO;
216 goto fail;
219 if((*param) != NULL)
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"));
227 result = -EIO;
228 goto fail;
231 if((*data) != NULL)
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"));
242 result = -EIO;
243 goto fail;
246 total_data = WVAL (inbuf, smb_tdrcnt);
247 total_param = WVAL (inbuf, smb_tprcnt);
248 if (total_data <= (*data_len) && total_param <= (*param_len))
249 break;
251 result = smb_receive (server, sock_fd);
252 if (result < 0)
253 goto fail;
255 if (server->rcls != 0)
257 result = -EIO;
258 goto fail;
262 LOG (("smb_receive_trans2: normal exit\n"));
263 return 0;
265 fail:
267 LOG (("smb_receive_trans2: failed exit\n"));
269 if((*param) != NULL)
270 free (*param);
272 if((*data) != NULL)
273 free (*data);
275 (*param) = (*data) = NULL;
277 return result;
281 smb_release (struct smb_server *server)
283 int result;
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)
291 result = (-errno);
292 goto out;
295 result = 0;
297 out:
299 return result;
303 smb_connect (struct smb_server *server)
305 int sock_fd = server->mount_data.fd;
306 int result;
308 if (sock_fd < 0)
310 result = (-EBADF);
311 goto out;
314 result = connect (sock_fd, (struct sockaddr *)&server->mount_data.addr, sizeof(struct sockaddr_in));
315 if(result < 0)
316 result = (-errno);
318 out:
320 return(result);
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)
333 int len, result;
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"));
340 result = -EBADF;
341 goto out;
344 if (server->state != CONN_VALID)
346 result = -EIO;
347 goto out;
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);
355 if (result < 0)
357 LOG (("smb_request: send error = %ld\n", errno));
359 result = (-errno);
361 else
363 result = smb_receive (server, sock_fd);
366 out:
368 if (result < 0)
370 server->state = CONN_INVALID;
371 smb_invalidate_all_inodes (server);
374 LOG (("smb_request: result = %ld\n", result));
376 return (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)
384 int len, result;
385 int sock_fd = server->mount_data.fd;
386 unsigned char *buffer = server->packet;
388 if (server->state != CONN_VALID)
390 result = -EIO;
391 goto out;
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);
399 if (result < 0)
401 LOG (("smb_trans2_request: send error = %ld\n", errno));
403 result = (-errno);
405 else
407 result = smb_receive_trans2 (server, sock_fd, data_len, param_len, data, param);
410 out:
412 if (result < 0)
414 server->state = CONN_INVALID;
415 smb_invalidate_all_inodes (server);
418 LOG (("smb_trans2_request: result = %ld\n", result));
420 return result;
423 /* target must be in user space */
425 smb_request_read_raw (struct smb_server *server, unsigned char *target, int max_len)
427 int len, result;
428 int sock_fd = server->mount_data.fd;
429 unsigned char *buffer = server->packet;
431 if (server->state != CONN_VALID)
433 result = -EIO;
434 goto out;
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));
447 if (result < 0)
449 LOG (("smb_request_read_raw: send error = %ld\n", errno));
451 result = (-errno);
453 else
455 result = smb_receive_raw (sock_fd, target, max_len, 0);
458 out:
460 if (result < 0)
462 server->state = CONN_INVALID;
463 smb_invalidate_all_inodes (server);
466 LOG (("smb_request_read_raw: result = %ld\n", result));
468 return 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)
477 int result;
478 byte nb_header[4];
479 int sock_fd = server->mount_data.fd;
481 if (server->state != CONN_VALID)
483 result = -EIO;
484 goto out;
487 smb_encode_smb_length (nb_header, length);
489 result = send (sock_fd, (void *) nb_header, 4, 0);
490 if (result == 4)
492 result = send (sock_fd, (void *) source, length, 0);
493 if(result < 0)
494 result = (-errno);
496 else
498 if(result < 0)
499 result = (-errno);
500 else
501 result = -EIO;
504 LOG (("smb_request_write_raw: send returned %ld\n", result));
506 if (result == length)
507 result = smb_receive (server, sock_fd);
509 out:
511 if (result < 0)
513 server->state = CONN_INVALID;
515 smb_invalidate_all_inodes (server);
518 if (result > 0)
519 result = length;
521 LOG (("smb_request_write_raw: result = %ld\n", result));
523 return result;