source: trunk/samba-3.0.25pre1/source/ndpsmb/smbcd.c@ 5

Last change on this file since 5 was 5, checked in by Yuri Dario, 18 years ago

OS/2 client code, initial import.

  • Property svn:eol-style set to native
File size: 25.1 KB
Line 
1#define INCL_DOSERRORS
2#define INCL_DOS
3#include <os2emx.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <stdarg.h>
7#include <sys/types.h>
8#include <process.h>
9#include <sys/time.h>
10#include "smbwrp.h"
11#include "smbcd.h"
12
13int debuglevel = 0;
14HMTX logmutex = 0;
15char *logfile = NULL;
16
17char *timestring(int hires);
18
19int debug_parse_levels(const char *params_str)
20{
21 return 1;
22}
23
24void dbgflush( void )
25{
26// if (!logfile) fflush(stdout);
27}
28
29int debuglvl(int level)
30{
31 return (level <= debuglevel) ? 1 : 0;
32}
33
34int debugheader(int level, char * file, char * func, int line)
35{
36 int rc;
37 if (level > debuglevel)
38 {
39 return 0;
40 }
41 rc = DosRequestMutexSem(logmutex, -1L);
42 if (rc)
43 {
44 return 0;
45 }
46 rc = 1;
47 do
48 {
49 FILE * f;
50 struct timeval tv;
51 time_t t;
52 char buf[80] = {0};
53 if (logfile)
54 {
55 f = fopen(logfile, "a");
56 if (!f)
57 {
58 rc = 0;
59 break;
60 }
61 }
62 else
63 {
64 f = stdout;
65 }
66 gettimeofday(&tv, NULL);
67 t = time(NULL);
68// strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime((time_t *)&tv.tv_sec));
69 strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime(&t));
70 fprintf(f, "%s.%d: %d %d: %s:%s(%d) :", buf, tv.tv_usec / 10000, level, _gettid(), file, func, line);
71 if (logfile)
72 {
73 fclose(f);
74 }
75 }
76 while (0);
77 DosReleaseMutexSem(logmutex);
78 return rc;
79}
80
81int debugmessage(char * fmt, ...)
82{
83 int rc;
84 rc = DosRequestMutexSem(logmutex, -1L);
85 if (rc)
86 {
87 return 0;
88 }
89 do
90 {
91 FILE * f;
92 va_list args;
93 if (logfile)
94 {
95 f = fopen(logfile, "a");
96 if (!f)
97 {
98 break;
99 }
100 }
101 else
102 {
103 f = stdout;
104 }
105 va_start(args, fmt);
106 vfprintf(f, fmt, args);
107 va_end(args);
108 if (logfile)
109 {
110 fclose(f);
111 }
112 }
113 while (0);
114 DosReleaseMutexSem(logmutex);
115 return 0;
116}
117
118void debuglocal(int level, char * fmt, ...)
119{
120 int rc;
121 if (level > debuglevel)
122 {
123 return;
124 }
125 rc = DosRequestMutexSem(logmutex, -1L);
126 if (rc)
127 {
128 return;
129 }
130 do
131 {
132 FILE * f;
133 struct timeval tv;
134 char buf[80] = {0};
135 va_list args;
136 if (logfile)
137 {
138 f = fopen(logfile, "a");
139 if (!f)
140 {
141 break;
142 }
143 }
144 else
145 {
146 f = stdout;
147 }
148 gettimeofday(&tv, NULL);
149 strftime(buf,sizeof(buf)-1,"%Y/%m/%d %H:%M:%S", localtime((time_t *)&tv.tv_sec));
150 fprintf(f, "%s.%d: %d %d: ", buf, tv.tv_usec / 10000, level, _gettid());
151 va_start(args, fmt);
152 vfprintf(f, fmt, args);
153 va_end(args);
154 if (logfile)
155 {
156 fclose(f);
157 }
158 }
159 while (0);
160 DosReleaseMutexSem(logmutex);
161}
162
163// map errno errors to API errors
164int maperror(int rc)
165{
166 switch (rc)
167 {
168 case 0 : return NO_ERROR ; /* NO_ERROR */
169 case 1 : return ERROR_ACCESS_DENIED ; /* EPERM - Operation not permitted */
170 case 2 : return ERROR_FILE_NOT_FOUND ; /* ENOENT - No such file or directory */
171 case 3 : return ERROR_PID_MISMATCH ; /* ESRCH - No such process */
172 case 4 : return ERROR_INTERRUPT ; /* EINTR - Interrupted system call */
173 case 5 : return ERROR_READ_FAULT ; /* EIO - I/O error */
174 case 6 : return ERROR_BAD_UNIT ; /* ENXIO - No such device or address */
175 case 7 : return ERROR_INVALID_DATA ; /* E2BIG - Arguments or environment too big */
176 case 8 : return ERROR_BAD_EXE_FORMAT ; /* ENOEXEC - Invalid executable file format */
177 case 9 : return ERROR_INVALID_HANDLE ; /* EBADF - Bad file number */
178 case 10 : return ERROR_NO_CHILD_PROCESS ; /* ECHILD - No child processes */
179 case 11 : return ERROR_BUSY ; /* EAGAIN - Resource temporarily unavailable */
180 case 12 : return ERROR_NOT_ENOUGH_MEMORY ; /* ENOMEM - Not enough memory */
181 case 13 : return ERROR_ACCESS_DENIED ; /* EACCES - Permission denied */
182 case 14 : return ERROR_INVALID_ADDRESS ; /* EFAULT - Bad address */
183 case 15 : return ERROR_NOT_LOCKED ; /* ENOLCK - No locks available */
184 case 16 : return ERROR_BUSY ; /* EBUSY - Resource busy */
185 case 17 : return ERROR_FILE_EXISTS ; /* EEXIST - File exists */
186 case 18 : return ERROR_NOT_SAME_DEVICE ; /* EXDEV - Cross-device link */
187 case 19 : return ERROR_REM_NOT_LIST ; /* ENODEV - No such device */
188 case 20 : return ERROR_PATH_NOT_FOUND ; /* ENOTDIR - Not a directory */
189 case 21 : return ERROR_DIRECTORY ; /* EISDIR - Is a directory */
190 case 22 : return ERROR_INVALID_PARAMETER ; /* EINVAL - Invalid argument */
191 case 23 : return ERROR_TOO_MANY_OPEN_FILES ; /* ENFILE - Too many open files in system */
192 case 24 : return ERROR_TOO_MANY_OPENS ; /* EMFILE - Too many open files */
193 case 25 : return ERROR_MOD_NOT_FOUND ; /* ENOTTY - Inappropriate ioctl */
194 case 26 : return ERROR_LOCK_VIOLATION ; /* EDEADLK - Resource deadlock avoided */
195 case 27 : return ERROR_TRANSFER_TOO_LONG ; /* EFBIG - File too large */
196 case 28 : return ERROR_DISK_FULL ; /* ENOSPC - Disk full */
197 case 29 : return ERROR_SEEK ; /* ESPIPE - Invalid seek */
198 case 30 : return ERROR_WRITE_PROTECT ; /* EROFS - Read-only file system */
199 case 31 : return ERROR_TOO_MANY_OPEN_FILES ; /* EMLINK - Too many links */
200 case 32 : return ERROR_BROKEN_PIPE ; /* EPIPE - Broken pipe */
201 case 33 : return ERROR_INVALID_LEVEL ; /* EDOM - Domain error */
202 case 34 : return ERROR_FILENAME_EXCED_RANGE ; /* ERANGE - Result too large */
203 case 35 : return ERROR_DIR_NOT_EMPTY ; /* ENOTEMPTY - Directory not empty */
204 case 36 : return ERROR_BUSY_DRIVE ; /* EINPROGRESS - Operation now in progress */
205 case 37 : return ERROR_INVALID_FUNCTION ; /* ENOSYS - Function not implemented */
206 case 38 : return ERROR_FILENAME_EXCED_RANGE ; /* ENAMETOOLONG - File name too long */
207 case 39 : return ERROR_KBD_FOCUS_REQUIRED ; /* EDESTADDRREQ - Destination address required */
208 case 40 : return ERROR_TRANSFER_TOO_LONG ; /* EMSGSIZE - Message too long */
209 case 48 : return ERROR_NETWORK_BUSY ; /* EADDRINUSE - Address already in use */
210 case 49 : return ERROR_INFO_NOT_AVAIL ; /* EADDRNOTAVAIL - Can't assigned requested address */
211 case 50 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETDOWN - Network is down */
212 case 51 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETUNREACH - Network is unreachable */
213 case 52 : return ERROR_NETWORK_ACCESS_DENIED ; /* ENETRESET - Network dropped connection on reset */
214 case 53 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNABORTED - Software caused connection abort */
215 case 54 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNRESET - Connection reset by peer */
216 case 55 : return ERROR_BUFFER_OVERFLOW ; /* ENOBUFS - No buffer space available */
217 case 56 : return ERROR_PIPE_BUSY ; /* EISCONN - Socket is already connected */
218 case 57 : return ERROR_PIPE_NOT_CONNECTED ; /* ENOTCONN - Socket is not connected */
219 case 58 : return ERROR_ALREADY_SHUTDOWN ; /* ESHUTDOWN - Can't send after socket shutdown */
220 case 60 : return ERROR_TIMEOUT ; /* ETIMEDOUT - Connection timed out */
221 case 61 : return ERROR_NETWORK_ACCESS_DENIED ; /* ECONNREFUSED - Connection refused */
222 case 63 : return ERROR_INVALID_BLOCK ; /* ENOTSOCK - Socket operation on non-socket */
223 case 64 : return ERROR_BAD_FORMAT ; /* EHOSTDOWN - Host is down */
224 case 65 : return ERROR_BAD_NETPATH ; /* EHOSTUNREACH - No route to host */
225 case 66 : return ERROR_BUSY_DRIVE ; /* EALREADY - Operation already in progress */
226 }
227 return rc + 40000;
228}
229
230char * getlastslash(char * path)
231{
232 char * p;
233 if (!path)
234 {
235 return NULL;
236 }
237 for (p = path + strlen(path) - 1; p >= path; p--)
238 {
239 if (*p == '\\' || *p == '/')
240 {
241 return p;
242 }
243 }
244 return NULL;
245}
246
247void _System add_dir_entry(void * st)
248{
249 int rc;
250 filelist_state * state = (filelist_state *)st;
251 if (!state || !*(state->finfo.fname))
252 {
253 return;
254 }
255 if (!state->data)
256 {
257 debuglocal(0,"Malformed filelist_state!\n");
258 return;
259 }
260 if (state->bufferlen < state->datalen + sizeof(state->finfo))
261 {
262 // send this portion of buffer to client
263 smb_request req = {0};
264 smb_response resp = {0};
265 unsigned long action;
266 resp.length = state->datalen;
267 resp.rc = ERROR_MORE_DATA;
268 rc = DosWrite(state->pipe, &resp, sizeof(resp), &action);
269 if (rc || action < sizeof(resp))
270 {
271 debuglocal(1,"Failed to write to pipe in add_dir_entry %d: %d %d\n", state->pipe, rc, action);
272 }
273 else
274 {
275 rc = DosRead(state->pipe, &req, sizeof(req), &action);
276 if (rc || action < sizeof(req))
277 {
278 debuglocal(0,"Failed to read from pipe in add_dir_entry %d: %d %d\n", state->pipe, rc, action);
279 return;
280 }
281 }
282 state->datalen = 0;
283 }
284 memcpy(state->data + state->datalen, &state->finfo, sizeof(state->finfo));
285 state->datalen += sizeof(state->finfo);
286}
287
288// rc = 0 - continue, rc = 1 - quit with response
289int processrequest(HPIPE pipe, cli_state * cli, unsigned long * reconnect, smbwrp_server * srv, smb_request *req, smb_response *res)
290{
291 int rc = 0;
292 int callrc = 0;
293 char * data;
294 if (!pipe || !cli || !reconnect || !srv || !req || !req->param || req->paramlen > req->length || !res)
295 {
296 debuglocal(0,"invalid structures\n");
297 return ERROR_INVALID_PARAMETER;
298 }
299 data = req->param + req->paramlen;
300// memset(res, 0, sizeof(*res));
301 debuglocal(1,"Client request %d paramlen %d len %d, reconnect %d. State %08x\n", req->request, req->paramlen, req->length, *reconnect, cli);
302 if (*reconnect == 2)
303 {
304 debuglocal(1,"Reconnecting to last server requested\n");
305 res->rc = smbwrp_connect(srv, cli);
306 if (res->rc)
307 {
308 debuglocal(1,"Client reconnect resprc %d\n", res->rc);
309 return NO_ERROR;
310 }
311 *reconnect = 1;
312 }
313 switch (req->request)
314 {
315 case SMBREQ_INIT :
316 {
317 res->value = sizeof(smbwrp_server) << 16 | getpid();
318 } break;
319 case SMBREQ_INITCOMPLETE :
320 {
321 callrc = DosGetSharedMem(req->param, PAG_READ | PAG_WRITE);
322 if (callrc)
323 {
324 debuglocal(0,"Cant get sharedmem of %x : %d\n", req->param, callrc);
325 res->rc = callrc;
326 rc = 1;
327 break;
328 }
329 } break;
330 case SMBREQ_CONNECT :
331 {
332 if (req->paramlen < sizeof(smbwrp_server))
333 {
334 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server));
335 res->rc = ERROR_INVALID_PARAMETER;
336 break;
337 }
338 res->rc = smbwrp_connect((smbwrp_server *)req->param, cli);
339 if (!res->rc)
340 {
341 memcpy(srv, req->param, sizeof(smbwrp_server));
342 *reconnect = 1;
343 }
344 } break;
345 case SMBREQ_DISCONNECT :
346 {
347 smbwrp_disconnect(cli);
348 } break;
349 case SMBREQ_OPEN :
350 {
351 if (req->paramlen < sizeof(smbwrp_file))
352 {
353 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
354 res->rc = ERROR_INVALID_PARAMETER;
355 break;
356 }
357 callrc = smbwrp_open(cli, (smbwrp_file *)req->param);
358 res->rc = maperror(callrc);
359 } break;
360 case SMBREQ_CLOSE :
361 {
362 if (req->paramlen < sizeof(smbwrp_file))
363 {
364 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
365 res->rc = ERROR_INVALID_PARAMETER;
366 break;
367 }
368 callrc = smbwrp_close(cli, (smbwrp_file *)req->param);
369 res->rc = maperror(callrc);
370 } break;
371 case SMBREQ_READ :
372 {
373 if (req->paramlen < sizeof(smbwrp_file))
374 {
375 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
376 res->rc = ERROR_INVALID_PARAMETER;
377 break;
378 }
379 callrc = smbwrp_read(cli, (smbwrp_file *)req->param,
380 data, req->length - req->paramlen, (unsigned long *)&res->value);
381 res->rc = maperror(callrc);
382 } break;
383 case SMBREQ_WRITE :
384 {
385 if (req->paramlen < sizeof(smbwrp_file))
386 {
387 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
388 res->rc = ERROR_INVALID_PARAMETER;
389 break;
390 }
391 callrc = smbwrp_write(cli, (smbwrp_file *)req->param,
392 data, req->length - req->paramlen, (unsigned long *)&res->value);
393 res->rc = maperror(callrc);
394 } break;
395 case SMBREQ_LSEEK :
396 {
397 if (req->paramlen < sizeof(smbwrp_file) + sizeof(int) + sizeof(long long))
398 {
399 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(int) + sizeof(long long));
400 res->rc = ERROR_INVALID_PARAMETER;
401 break;
402 }
403 callrc = smbwrp_lseek(cli,
404 (smbwrp_file *)req->param,
405 *(int *)(req->param + sizeof(smbwrp_file)),
406 *(long long *)(req->param + sizeof(smbwrp_file) + sizeof(int)));
407 res->rc = maperror(callrc);
408 } break;
409 case SMBREQ_SETINFO :
410 {
411 if (req->paramlen < sizeof(smbwrp_fileinfo))
412 {
413 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_fileinfo));
414 res->rc = ERROR_INVALID_PARAMETER;
415 break;
416 }
417 callrc = smbwrp_setattr(cli, (smbwrp_fileinfo *)req->param);
418 res->rc = maperror(callrc);
419 } break;
420 case SMBREQ_GETINFO :
421 {
422 if (req->length < sizeof(smbwrp_fileinfo))
423 {
424 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_fileinfo));
425 res->rc = ERROR_INVALID_PARAMETER;
426 break;
427 }
428 callrc = smbwrp_getattr(cli, (smbwrp_fileinfo *)req->param);
429 res->rc = maperror(callrc);
430 } break;
431 case SMBREQ_FGETINFO :
432 {
433 if (req->length < sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo))
434 {
435 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(smbwrp_fileinfo));
436 res->rc = ERROR_INVALID_PARAMETER;
437 break;
438 }
439 callrc = smbwrp_fgetattr(cli,
440 (smbwrp_file *)req->param,
441 (smbwrp_fileinfo *)(req->param + sizeof(smbwrp_file)));
442 res->rc = maperror(callrc);
443 } break;
444 case SMBREQ_FILELIST :
445 {
446 filelist_state state;
447 char * p;
448 if (req->paramlen < sizeof(smbwrp_server) + (CCHMAXPATH + 1))
449 {
450 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_server) + (CCHMAXPATH + 1));
451 res->rc = ERROR_INVALID_PARAMETER;
452 break;
453 }
454 state.pipe = pipe;
455 state.bufferlen = req->length - req->paramlen;
456 if (state.bufferlen < sizeof(state))
457 {
458 debuglocal(0,"Not enough buffer to hold data %d\n", state.bufferlen);
459 res->rc = ERROR_BUFFER_OVERFLOW;
460 break;
461 }
462 strncpy(state.mask, req->param + sizeof(smbwrp_server), sizeof(state.mask) - 2);
463 p = getlastslash(state.mask);
464 if (p)
465 {
466 *(p + 1) = '*';
467 *(p + 2) = 0;
468 }
469 else
470 {
471 strcpy(state.mask, "\\*");
472 }
473 state.data = data;
474 state.datalen = 0;
475 state.add_dir_entry = add_dir_entry;
476 callrc = smbwrp_filelist((smbwrp_server *)req->param, cli, &state);
477 res->rc = maperror(callrc);
478 res->length = state.datalen;
479 } break;
480 case SMBREQ_RENAME :
481 {
482 if (req->paramlen < 2 * (CCHMAXPATH + 1))
483 {
484 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, 2 * (CCHMAXPATH + 1));
485 res->rc = ERROR_INVALID_PARAMETER;
486 break;
487 }
488 callrc = smbwrp_rename(cli, req->param,
489 req->param + (CCHMAXPATH + 1));
490 res->rc = maperror(callrc);
491 } break;
492 case SMBREQ_UNLINK :
493 {
494 if (req->paramlen < CCHMAXPATH + 1)
495 {
496 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
497 res->rc = ERROR_INVALID_PARAMETER;
498 break;
499 }
500 callrc = smbwrp_unlink(cli, req->param);
501 res->rc = maperror(callrc);
502 } break;
503 case SMBREQ_MKDIR :
504 {
505 if (req->paramlen < CCHMAXPATH + 1)
506 {
507 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
508 res->rc = ERROR_INVALID_PARAMETER;
509 break;
510 }
511 callrc = smbwrp_mkdir(cli, req->param);
512 res->rc = maperror(callrc);
513 } break;
514 case SMBREQ_RMDIR :
515 {
516 if (req->paramlen < CCHMAXPATH + 1)
517 {
518 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
519 res->rc = ERROR_INVALID_PARAMETER;
520 break;
521 }
522 callrc = smbwrp_rmdir(cli, req->param);
523 res->rc = maperror(callrc);
524 } break;
525 case SMBREQ_CHDIR :
526 {
527 if (req->paramlen < CCHMAXPATH + 1)
528 {
529 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
530 res->rc = ERROR_INVALID_PARAMETER;
531 break;
532 }
533 callrc = smbwrp_chdir(cli, req->param);
534 res->rc = maperror(callrc);
535 } break;
536 case SMBREQ_NEWSIZE :
537 {
538 if (req->paramlen < sizeof(smbwrp_file) + sizeof(off_t))
539 {
540 debuglocal(0,"Not enough data in request %d of %d\n", req->length, sizeof(smbwrp_file) + sizeof(off_t));
541 res->rc = ERROR_INVALID_PARAMETER;
542 break;
543 }
544 callrc = smbwrp_setfilesize(cli,
545 (smbwrp_file *)req->param,
546 *(off_t *)(req->param + sizeof(smbwrp_file)));
547 res->rc = maperror(callrc);
548 } break;
549 case SMBREQ_SETEA :
550 {
551 // got FEA there
552 FEALIST * pfealist;
553 FEA * pfea;
554 unsigned long done = sizeof(long);
555 if (req->paramlen < CCHMAXPATH + 1 + sizeof(FEALIST))
556 {
557 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + sizeof(FEALIST));
558 res->rc = ERROR_INVALID_PARAMETER;
559 break;
560 }
561 pfealist = (FEALIST *)(req->param + CCHMAXPATH + 1);
562 if (req->paramlen < CCHMAXPATH + 1 + pfealist->cbList)
563 {
564 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1 + pfealist->cbList);
565 res->rc = ERROR_INVALID_PARAMETER;
566 break;
567 }
568 pfea = pfealist->list;
569 while (done < pfealist->cbList)
570 {
571 callrc = smbwrp_setea(cli, req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
572 if (callrc)
573 {
574 break;
575 }
576 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
577 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
578 }
579 res->rc = maperror(callrc);
580 } break;
581 case SMBREQ_FSETEA :
582 {
583 // got FEA there
584 FEALIST * pfealist;
585 FEA * pfea;
586 unsigned long done = sizeof(long);
587 if (req->paramlen < sizeof(smbwrp_file) + sizeof(FEALIST))
588 {
589 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + sizeof(FEALIST));
590 res->rc = ERROR_INVALID_PARAMETER;
591 break;
592 }
593 pfealist = (FEALIST *)(req->param + sizeof(smbwrp_file));
594 if (req->paramlen < sizeof(smbwrp_file) + pfealist->cbList)
595 {
596 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file) + pfealist->cbList);
597 res->rc = ERROR_INVALID_PARAMETER;
598 break;
599 }
600 pfea = pfealist->list;
601 while (done < pfealist->cbList)
602 {
603 callrc = smbwrp_fsetea(cli, (smbwrp_file *)req->param, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
604 if (callrc)
605 {
606 break;
607 }
608 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
609 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
610 }
611 res->rc = maperror(callrc);
612 } break;
613 case SMBREQ_LISTEA :
614 {
615 FEALIST * pfealist;
616 if (req->paramlen < CCHMAXPATH + 1)
617 {
618 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, CCHMAXPATH + 1);
619 res->rc = ERROR_INVALID_PARAMETER;
620 break;
621 }
622 pfealist = (FEALIST *)data;
623 callrc = smbwrp_listea(cli, req->param, data, req->length);
624 res->rc = maperror(callrc);
625 if (!res->rc && pfealist->cbList > req->length)
626 {
627 res->rc = ERROR_BUFFER_OVERFLOW;
628 }
629 } break;
630 case SMBREQ_FLISTEA :
631 {
632 FEALIST * pfealist;
633 if (req->paramlen < sizeof(smbwrp_file))
634 {
635 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(smbwrp_file));
636 res->rc = ERROR_INVALID_PARAMETER;
637 break;
638 }
639 pfealist = (FEALIST *)data;
640 callrc = smbwrp_flistea(cli, (smbwrp_file *)req->param, data, req->length);
641 res->rc = maperror(callrc);
642 if (!res->rc && pfealist->cbList > req->length)
643 {
644 res->rc = ERROR_BUFFER_OVERFLOW;
645 }
646 } break;
647 case SMBREQ_DSKATTR :
648 {
649 if (req->paramlen < sizeof(FSALLOCATE))
650 {
651 debuglocal(0,"Not enough data in request %d of %d\n", req->paramlen, sizeof(FSALLOCATE));
652 res->rc = ERROR_INVALID_PARAMETER;
653 break;
654 }
655 callrc = smbwrp_dskattr(cli, (FSALLOCATE*)req->param);
656 res->rc = maperror(callrc);
657 res->length = callrc ? 0 : req->length;
658 } break;
659 default :
660 {
661 debuglocal(0,"Unknown request %d\n", req->request);
662 // rc = ERROR_INVALID_FUNCTION; ??
663 res->rc = ERROR_INVALID_FUNCTION;
664 }
665 }
666 debuglocal(1,"Client request %d rc %d resprc %d resplength %d\n", req->request, rc, res->rc, res->length);
667 if (res->rc == ERROR_PIPE_NOT_CONNECTED && *reconnect == 1)
668 {
669 debuglocal(1,"Setting reconnect flag\n");
670 *reconnect = 2;
671 }
672 return rc;
673}
674
675void clientthread(void * arg)
676{
677 HPIPE pipe;
678 int rc;
679 smbwrp_server srv = {0};
680 smb_request req = {0};
681 smb_response resp = {0};
682 unsigned long reconnect = 0;
683 unsigned long action;
684 cli_state * cli;
685
686 if (!arg)
687 {
688 debuglocal(0,"Passed null pipe pointer\n");
689 return;
690 }
691 pipe = (HPIPE)arg;
692 rc = DosAllocMem((PPVOID)&cli, smbwrp_getclisize(), PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
693 if (rc)
694 {
695 rc = DosAllocMem((PPVOID)&cli, smbwrp_getclisize(), PAG_COMMIT | PAG_READ | PAG_WRITE);
696 }
697 cli = (cli_state *)calloc(smbwrp_getclisize(), 1);
698 if (rc || !cli)
699 {
700 debuglocal(0,"Not enough memory to initialize client structure\n");
701 DosClose(pipe);
702 return;
703 }
704 memset(cli, 0, smbwrp_getclisize());
705 debuglocal(0,"opening client pipe %d\n", pipe);
706 for (;;)
707 {
708 rc = DosRead(pipe, &req, sizeof(req), &action);
709 if (rc || action < sizeof(req))
710 {
711 debuglocal(0,"Failed to read from pipe %d: %d %d\n", pipe, rc, action);
712 break;
713 }
714 // rc = 0 - continue, rc = 1 - quit with response
715 memset(&resp, 0, sizeof(resp));
716 rc = processrequest(pipe, cli, &reconnect, &srv, &req, &resp);
717 if (rc < 2)
718 {
719 rc = DosWrite(pipe, &resp, sizeof(resp), &action);
720 if (rc || action < sizeof(resp))
721 {
722 debuglocal(0,"Failed to write to pipe %d: %d %d\n", pipe, rc, action);
723 }
724 }
725 if (rc)
726 {
727 debuglocal(0,"shutdown client %d with rc %d\n", pipe, rc);
728 break;
729 }
730 }
731 debuglocal(0,"closing client pipe %d\n", pipe);
732 DosDisConnectNPipe(pipe);
733 DosClose(pipe);
734 memset(cli, 0, smbwrp_getclisize());
735 DosFreeMem(cli);
736}
737
738void help(void)
739{
740 printf("Usage: smbcd [-d/--debug <debuglevel>] [-q/--quiet] [-l/--logfile <logfile>]\n");
741}
742
743int main(int argc, char ** argv)
744{
745 int rc = 0, quiet = 0;
746 HPIPE pipe, newpipe;
747 unsigned long action;
748 for (argc--, argv++; argc > 0; argc--, argv++)
749 {
750 if (strcmp(argv[0], "-d") == 0 || strcmp(argv[0], "--debug") == 0)
751 {
752 if (argc < 2)
753 {
754 rc = 1;
755 printf("Parameter missing after <%s>", argv[0]);
756 break;
757 }
758 debuglevel = atoi(argv[1]);
759 if (debuglevel <= 0 || debuglevel > 10)
760 {
761 rc = 1;
762 printf("Wrong value <%s> for parameter <%s>", argv[1], argv[0]);
763 break;
764 }
765 if (debuglevel == 10)
766 {
767 // smbcd crashed on dump_msg used to dump messages on level 10
768 debuglevel--;
769 }
770 argc --;
771 argv ++;
772 } else
773 if (strcmp(argv[0], "-l") == 0 || strcmp(argv[0], "--logfile") == 0)
774 {
775 FILE * test;
776 if (argc < 2)
777 {
778 rc = 1;
779 printf("Parameter missing after <%s>", argv[0]);
780 break;
781 }
782 logfile = argv[1];
783 test = fopen(argv[1], "a");
784 if (test == NULL)
785 {
786 rc = 1;
787 printf("Cant open log file <%s>\n", logfile);
788 break;
789 }
790 fclose(test);
791 argc --;
792 argv ++;
793 } else
794 if (strcmp(argv[0], "-q") == 0 || strcmp(argv[0], "--quiet") == 0)
795 {
796 quiet = 1;
797 } else
798 {
799 printf("Unknown parameter <%s>\n", argv[0]);
800 rc = 1;
801 break;
802 }
803 }
804 if (rc)
805 {
806 help();
807 return 1;
808 }
809 if (quiet)
810 {
811 debuglevel = -10;
812 }
813 rc = DosCreateMutexSem(NULL, &logmutex, 0, 0);
814 if (rc)
815 {
816 if (!quiet) printf("DosCreateMutexSem %d\n", rc);
817 return 1;
818 }
819 rc = smbwrp_init();
820 if (rc)
821 {
822 debuglocal(0,"Init failed with rc %d\n", rc);
823 return 1;
824 }
825 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
826 if (rc == NO_ERROR)
827 {
828 debuglocal(0,"Pipe %s already exists. May be duplicate smbcd is running\n", PIPENAME);
829 DosClose(pipe);
830 return 1;
831 }
832
833 rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
834 NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
835 600, 600, 1000);
836 if (rc)
837 {
838 debuglocal(0,"Cant create named pipe %d\n", rc);
839 return 1;
840 }
841
842 debuglocal(1,"Entering main loop. My pid is %d. My mutex is %08x. My debuglevel is %d. Client state size %d\n", getpid(), logmutex, debuglevel, smbwrp_getclisize());
843
844 for (;;)
845 {
846 do
847 {
848 rc = DosConnectNPipe(pipe);
849 } while (rc == ERROR_INTERRUPT);
850
851 if (!rc)
852 {
853 debuglocal(1,"New client connected %d to pipe %d\n", rc, pipe);
854 int tid = _beginthread(clientthread, NULL, 655360, (void *)pipe);
855 if (tid < 0)
856 {
857 debuglocal(0,"Failed to create client thread\n");
858 rc = 0xFFFF;
859 }
860 }
861
862 if (rc)
863 {
864 debuglocal(0,"Client failed to connect %d\n", rc);
865 DosDisConnectNPipe(pipe);
866 DosClose(pipe);
867 }
868
869 rc = DosCreateNPipe(PIPENAME, &pipe, NP_ACCESS_DUPLEX,
870 NP_WAIT | NP_TYPE_MESSAGE | NP_READMODE_MESSAGE | SMBCD_MAX_THREADS,
871 600, 600, 1000);
872 if (rc)
873 {
874 debuglocal(0,"Cant create new named pipe %d\n", rc);
875 break;
876 }
877 }
878
879 DosDisConnectNPipe(pipe);
880 DosClose(pipe);
881 DosCloseMutexSem(logmutex);
882 return 0;
883}
Note: See TracBrowser for help on using the repository browser.