source: branches/samba-3.0/source/ndpsmb/smbcd.c@ 107

Last change on this file since 107 was 107, checked in by Paul Smedley, 18 years ago

Add configurable kerberos support for Netdrive plugin

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