source: branches/client-1.5/src/smbcd.c@ 144

Last change on this file since 144 was 130, checked in by Yuri Dario, 17 years ago

Return bad net name error if a printer or non existing share is used. ticket:58.

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