3ea918f6463056436a32768cbb9830b6e090932a
[reactos.git] / reactos / base / services / tftpd / tftpd.cpp
1 /**************************************************************************
2 * Copyright (C) 2005 by Achal Dhir *
3 * achaldhir@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 // TFTPServer.cpp
21
22 #include <stdio.h>
23 #include <winsock2.h>
24 #include <process.h>
25 #include <time.h>
26 #include <tchar.h>
27 #include <ws2tcpip.h>
28 #include <limits.h>
29 #include <iphlpapi.h>
30 #include "tftpd.h"
31
32 //Global Variables
33 char serviceName[] = "TFTPServer";
34 char displayName[] = "TFTP Server Multithreaded";
35 char sVersion[] = "TFTP Server MultiThreaded Version 1.61 Windows Built 1611";
36 char iniFile[_MAX_PATH];
37 char logFile[_MAX_PATH];
38 char tempbuff[256];
39 char logBuff[512];
40 char fileSep = '\\';
41 char notFileSep = '/';
42 WORD blksize = 65464;
43 char verbatim = 0;
44 WORD timeout = 3;
45 data2 cfig;
46 //ThreadPool Variables
47 HANDLE tEvent;
48 HANDLE cEvent;
49 HANDLE sEvent;
50 HANDLE lEvent;
51 BYTE currentServer = UCHAR_MAX;
52 WORD totalThreads=0;
53 WORD minThreads=1;
54 WORD activeThreads=0;
55
56 //Service Variables
57 SERVICE_STATUS serviceStatus;
58 SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
59 HANDLE stopServiceEvent = 0;
60
61 void WINAPI ServiceControlHandler(DWORD controlCode)
62 {
63 switch (controlCode)
64 {
65 case SERVICE_CONTROL_INTERROGATE:
66 break;
67
68 case SERVICE_CONTROL_SHUTDOWN:
69 case SERVICE_CONTROL_STOP:
70 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
71 SetServiceStatus(serviceStatusHandle, &serviceStatus);
72
73 SetEvent(stopServiceEvent);
74 return ;
75
76 case SERVICE_CONTROL_PAUSE:
77 break;
78
79 case SERVICE_CONTROL_CONTINUE:
80 break;
81
82 default:
83 if (controlCode >= 128 && controlCode <= 255)
84 break;
85 else
86 break;
87 }
88
89 SetServiceStatus(serviceStatusHandle, &serviceStatus);
90 }
91
92 void WINAPI ServiceMain(DWORD /*argc*/, TCHAR* /*argv*/[])
93 {
94 serviceStatus.dwServiceType = SERVICE_WIN32;
95 serviceStatus.dwCurrentState = SERVICE_STOPPED;
96 serviceStatus.dwControlsAccepted = 0;
97 serviceStatus.dwWin32ExitCode = NO_ERROR;
98 serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
99 serviceStatus.dwCheckPoint = 0;
100 serviceStatus.dwWaitHint = 0;
101
102 serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
103
104 if (serviceStatusHandle)
105 {
106 serviceStatus.dwCurrentState = SERVICE_START_PENDING;
107 SetServiceStatus(serviceStatusHandle, &serviceStatus);
108
109 //init
110 verbatim = false;
111 init();
112 fd_set readfds;
113 timeval tv;
114 tv.tv_sec = 20;
115 tv.tv_usec = 0;
116
117 stopServiceEvent = CreateEvent(0, FALSE, FALSE, 0);
118
119 serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
120 serviceStatus.dwCurrentState = SERVICE_RUNNING;
121 SetServiceStatus(serviceStatusHandle, &serviceStatus);
122
123 do
124 {
125 FD_ZERO(&readfds);
126
127 for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].port; i++)
128 FD_SET(cfig.tftpConn[i].sock, &readfds);
129
130 int fdsReady = select(cfig.maxFD, &readfds, NULL, NULL, &tv);
131
132 for (int i = 0; fdsReady > 0 && i < MAX_SERVERS && cfig.tftpConn[i].port; i++)
133 {
134 if (FD_ISSET(cfig.tftpConn[i].sock, &readfds))
135 {
136 WaitForSingleObject(sEvent, INFINITE);
137
138 currentServer = i;
139
140 if (!totalThreads || activeThreads >= totalThreads)
141 {
142 _beginthread(
143 processRequest, // thread function
144 0, // default security attributes
145 NULL); // argument to thread function
146
147 }
148
149 SetEvent(tEvent);
150 WaitForSingleObject(sEvent, INFINITE);
151 fdsReady--;
152 SetEvent(sEvent);
153 }
154 }
155 }
156 while (WaitForSingleObject(stopServiceEvent, 0) == WAIT_TIMEOUT);
157
158 if (cfig.logfile)
159 fclose(cfig.logfile);
160
161 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
162 SetServiceStatus(serviceStatusHandle, &serviceStatus);
163
164 sprintf(logBuff, "Closing Network Connections...");
165 logMess(logBuff, 1);
166
167 for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].port; i++)
168 closesocket(cfig.tftpConn[i].sock);
169
170 WSACleanup();
171
172 sprintf(logBuff, "TFTP Server Stopped !");
173 logMess(logBuff, 1);
174
175 serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
176 serviceStatus.dwCurrentState = SERVICE_STOPPED;
177 SetServiceStatus(serviceStatusHandle, &serviceStatus);
178 CloseHandle(stopServiceEvent);
179 stopServiceEvent = 0;
180 }
181 }
182
183 void runService()
184 {
185 SERVICE_TABLE_ENTRY serviceTable[] =
186 {
187 {serviceName, ServiceMain},
188 {0, 0}
189 };
190
191 StartServiceCtrlDispatcher(serviceTable);
192 }
193
194 bool stopService(SC_HANDLE service)
195 {
196 if (service)
197 {
198 SERVICE_STATUS serviceStatus;
199 QueryServiceStatus(service, &serviceStatus);
200 if (serviceStatus.dwCurrentState != SERVICE_STOPPED)
201 {
202 ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus);
203 printf("Stopping Service.");
204 for (int i = 0; i < 100; i++)
205 {
206 QueryServiceStatus(service, &serviceStatus);
207 if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
208 {
209 printf("Stopped\n");
210 return true;
211 }
212 else
213 {
214 Sleep(500);
215 printf(".");
216 }
217 }
218 printf("Failed\n");
219 return false;
220 }
221 }
222 return true;
223 }
224
225 void installService()
226 {
227 SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
228
229 if (serviceControlManager)
230 {
231 SC_HANDLE service = OpenService(serviceControlManager,
232 serviceName, SERVICE_QUERY_STATUS);
233 if (service)
234 {
235 printf("Service Already Exists..\n");
236 StartService(service,0,NULL);
237 CloseServiceHandle(service);
238 }
239 else
240 {
241 TCHAR path[ _MAX_PATH + 1 ];
242 if (GetModuleFileName(0, path, sizeof(path) / sizeof(path[0])) > 0)
243 {
244 SC_HANDLE service = CreateService(serviceControlManager,
245 serviceName, displayName,
246 SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
247 SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
248 0, 0, 0, 0, 0);
249 if (service)
250 {
251 printf("Successfully installed.. !\n");
252 StartService(service,0,NULL);
253 CloseServiceHandle(service);
254 }
255 else
256 printf("Installation Failed..\n");
257 }
258 }
259 CloseServiceHandle(serviceControlManager);
260 }
261 else
262 printWindowsError();
263 }
264
265 void uninstallService()
266 {
267 SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
268
269 if (serviceControlManager)
270 {
271 SC_HANDLE service = OpenService(serviceControlManager,
272 serviceName, SERVICE_QUERY_STATUS | SERVICE_STOP | DELETE);
273 if (service)
274 {
275 if (stopService(service))
276 {
277 DeleteService(service);
278 printf("Successfully Removed !\n");
279 }
280 else
281 printf("Failed to Stop Service..\n");
282
283 CloseServiceHandle(service);
284 }
285
286 CloseServiceHandle(serviceControlManager);
287 }
288 else
289 printWindowsError();
290 }
291
292 void printWindowsError()
293 {
294 DWORD dw = GetLastError();
295
296 if (dw)
297 {
298 LPVOID lpMsgBuf;
299
300 FormatMessage(
301 FORMAT_MESSAGE_ALLOCATE_BUFFER |
302 FORMAT_MESSAGE_FROM_SYSTEM |
303 FORMAT_MESSAGE_IGNORE_INSERTS,
304 NULL,
305 dw,
306 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
307 (LPTSTR) &lpMsgBuf,
308 0, NULL );
309
310 printf("Error: %p\nPress Enter..\n", lpMsgBuf);
311 getchar();
312 }
313 }
314
315 int main(int argc, TCHAR* argv[])
316 {
317 OSVERSIONINFO osvi;
318 osvi.dwOSVersionInfoSize = sizeof(osvi);
319 bool result = GetVersionEx(&osvi);
320
321 if (result && osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT)
322 {
323 if (argc > 1 && lstrcmpi(argv[1], TEXT("-i")) == 0)
324 installService();
325 else if (argc > 1 && lstrcmpi(argv[1], TEXT("-u")) == 0)
326 uninstallService();
327 else if (argc > 1 && lstrcmpi(argv[1], TEXT("-v")) == 0)
328 {
329 SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
330 bool serviceStopped = true;
331
332 if (serviceControlManager)
333 {
334 SC_HANDLE service = OpenService(serviceControlManager,
335 serviceName, SERVICE_QUERY_STATUS | SERVICE_STOP);
336 if (service)
337 {
338 serviceStopped = stopService(service);
339 CloseServiceHandle(service);
340 }
341 CloseServiceHandle(serviceControlManager);
342 }
343 else
344 printWindowsError();
345
346 if (serviceStopped)
347 runProg();
348 else
349 printf("Failed to Stop Service\n");
350 }
351 else
352 runService();
353 }
354 else if (argc == 1 || lstrcmpi(argv[1], TEXT("-v")) == 0)
355 runProg();
356 else
357 printf("This option is not available on Windows95/98/ME\n");
358
359 return 0;
360 }
361
362 void runProg()
363 {
364 verbatim = true;
365 init();
366 fd_set readfds;
367 timeval tv;
368 int fdsReady = 0;
369 tv.tv_sec = 20;
370 tv.tv_usec = 0;
371
372 printf("\naccepting requests..\n");
373
374 do
375 {
376 //printf("Active=%u Total=%u\n",activeThreads, totalThreads);
377
378 FD_ZERO(&readfds);
379
380 for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].port; i++)
381 FD_SET(cfig.tftpConn[i].sock, &readfds);
382
383 fdsReady = select(cfig.maxFD, &readfds, NULL, NULL, &tv);
384
385 //if (errno)
386 // printf("%s\n", strerror(errno));
387
388 for (int i = 0; fdsReady > 0 && i < MAX_SERVERS && cfig.tftpConn[i].port; i++)
389 {
390 if (FD_ISSET(cfig.tftpConn[i].sock, &readfds))
391 {
392 //printf("Request Waiting\n");
393
394 WaitForSingleObject(sEvent, INFINITE);
395
396 currentServer = i;
397
398 if (!totalThreads || activeThreads >= totalThreads)
399 {
400 _beginthread(
401 processRequest, // thread function
402 0, // default security attributes
403 NULL); // argument to thread function
404 }
405 SetEvent(tEvent);
406
407 //printf("thread signalled=%u\n",SetEvent(tEvent));
408
409 WaitForSingleObject(sEvent, INFINITE);
410 fdsReady--;
411 SetEvent(sEvent);
412 }
413 }
414 }
415 while (true);
416
417 for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].port; i++)
418 closesocket(cfig.tftpConn[i].sock);
419
420 WSACleanup();
421 }
422
423 void processRequest(void *lpParam)
424 {
425 //printf("New Thread %u\n",GetCurrentThreadId());
426
427 request req;
428
429 WaitForSingleObject(cEvent, INFINITE);
430 totalThreads++;
431 SetEvent(cEvent);
432
433 do
434 {
435 WaitForSingleObject(tEvent, INFINITE);
436 //printf("In Thread %u\n",GetCurrentThreadId());
437
438 WaitForSingleObject(cEvent, INFINITE);
439 activeThreads++;
440 SetEvent(cEvent);
441
442 if (currentServer >= MAX_SERVERS || !cfig.tftpConn[currentServer].port)
443 {
444 SetEvent(sEvent);
445 req.attempt = UCHAR_MAX;
446 continue;
447 }
448
449 memset(&req, 0, sizeof(request));
450 req.sock = INVALID_SOCKET;
451
452 req.clientsize = sizeof(req.client);
453 req.sockInd = currentServer;
454 currentServer = UCHAR_MAX;
455 req.knock = cfig.tftpConn[req.sockInd].sock;
456
457 if (req.knock == INVALID_SOCKET)
458 {
459 SetEvent(sEvent);
460 req.attempt = UCHAR_MAX;
461 continue;
462 }
463
464 errno = 0;
465 req.bytesRecd = recvfrom(req.knock, (char*)&req.mesin, sizeof(message), 0, (sockaddr*)&req.client, &req.clientsize);
466 errno = WSAGetLastError();
467
468 //printf("socket Signalled=%u\n",SetEvent(sEvent));
469 SetEvent(sEvent);
470
471 if (!errno && req.bytesRecd > 0)
472 {
473 if (cfig.hostRanges[0].rangeStart)
474 {
475 DWORD iip = ntohl(req.client.sin_addr.s_addr);
476 bool allowed = false;
477
478 for (int j = 0; j <= 32 && cfig.hostRanges[j].rangeStart; j++)
479 {
480 if (iip >= cfig.hostRanges[j].rangeStart && iip <= cfig.hostRanges[j].rangeEnd)
481 {
482 allowed = true;
483 break;
484 }
485 }
486
487 if (!allowed)
488 {
489 req.serverError.opcode = htons(5);
490 req.serverError.errorcode = htons(2);
491 strcpy(req.serverError.errormessage, "Access Denied");
492 logMess(&req, 1);
493 sendto(req.knock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize);
494 req.attempt = UCHAR_MAX;
495 continue;
496 }
497 }
498
499 if ((htons(req.mesin.opcode) == 5))
500 {
501 sprintf(req.serverError.errormessage, "Error Code %i at Client, %s", ntohs(req.clientError.errorcode), req.clientError.errormessage);
502 logMess(&req, 2);
503 req.attempt = UCHAR_MAX;
504 continue;
505 }
506 else if (htons(req.mesin.opcode) != 1 && htons(req.mesin.opcode) != 2)
507 {
508 req.serverError.opcode = htons(5);
509 req.serverError.errorcode = htons(5);
510 sprintf(req.serverError.errormessage, "Unknown Transfer Id");
511 logMess(&req, 2);
512 sendto(req.knock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize);
513 req.attempt = UCHAR_MAX;
514 continue;
515 }
516 }
517 else
518 {
519 sprintf(req.serverError.errormessage, "Communication Error");
520 logMess(&req, 1);
521 req.attempt = UCHAR_MAX;
522 continue;
523 }
524
525 req.blksize = 512;
526 req.timeout = timeout;
527 req.expiry = time(NULL) + req.timeout;
528 bool fetchAck = false;
529
530 req.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
531
532 if (req.sock == INVALID_SOCKET)
533 {
534 req.serverError.opcode = htons(5);
535 req.serverError.errorcode = htons(0);
536 strcpy(req.serverError.errormessage, "Thread Socket Creation Error");
537 sendto(req.knock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize);
538 logMess(&req, 1);
539 req.attempt = UCHAR_MAX;
540 continue;
541 }
542
543 sockaddr_in service;
544 service.sin_family = AF_INET;
545 service.sin_addr.s_addr = cfig.tftpConn[req.sockInd].server;
546
547 if (cfig.minport)
548 {
549 for (WORD comport = cfig.minport; ; comport++)
550 {
551 service.sin_port = htons(comport);
552
553 if (comport > cfig.maxport)
554 {
555 req.serverError.opcode = htons(5);
556 req.serverError.errorcode = htons(0);
557 strcpy(req.serverError.errormessage, "No port is free");
558 sendto(req.knock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize);
559 logMess(&req, 1);
560 req.attempt = UCHAR_MAX;
561 break;
562 }
563 else if (bind(req.sock, (sockaddr*) &service, sizeof(service)) == -1)
564 continue;
565 else
566 break;
567 }
568 }
569 else
570 {
571 service.sin_port = 0;
572
573 if (bind(req.sock, (sockaddr*) &service, sizeof(service)) == -1)
574 {
575 strcpy(req.serverError.errormessage, "Thread failed to bind");
576 sendto(req.knock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize);
577 logMess(&req, 1);
578 req.attempt = UCHAR_MAX;
579 }
580 }
581
582 if (req.attempt >= 3)
583 continue;
584
585 if (connect(req.sock, (sockaddr*)&req.client, req.clientsize) == -1)
586 {
587 req.serverError.opcode = htons(5);
588 req.serverError.errorcode = htons(0);
589 strcpy(req.serverError.errormessage, "Connect Failed");
590 sendto(req.knock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize);
591 logMess(&req, 1);
592 req.attempt = UCHAR_MAX;
593 continue;
594 }
595
596 //sprintf(req.serverError.errormessage, "In Temp, Socket");
597 //logMess(&req, 1);
598
599 char *inPtr = req.mesin.buffer;
600 *(inPtr + (req.bytesRecd - 3)) = 0;
601 req.filename = inPtr;
602
603 if (!strlen(req.filename) || strlen(req.filename) > UCHAR_MAX)
604 {
605 req.serverError.opcode = htons(5);
606 req.serverError.errorcode = htons(4);
607 strcpy(req.serverError.errormessage, "Malformed Request, Invalid/Missing Filename");
608 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
609 req.attempt = UCHAR_MAX;
610 logMess(&req, 1);
611 continue;
612 }
613
614 inPtr += strlen(inPtr) + 1;
615 req.mode = inPtr;
616
617 if (!strlen(req.mode) || strlen(req.mode) > 25)
618 {
619 req.serverError.opcode = htons(5);
620 req.serverError.errorcode = htons(4);
621 strcpy(req.serverError.errormessage, "Malformed Request, Invalid/Missing Mode");
622 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
623 req.attempt = UCHAR_MAX;
624 logMess(&req, 1);
625 continue;
626 }
627
628 inPtr += strlen(inPtr) + 1;
629
630 for (DWORD i = 0; i < strlen(req.filename); i++)
631 if (req.filename[i] == notFileSep)
632 req.filename[i] = fileSep;
633
634 tempbuff[0] = '.';
635 tempbuff[1] = '.';
636 tempbuff[2] = fileSep;
637 tempbuff[3] = 0;
638
639 if (strstr(req.filename, tempbuff))
640 {
641 req.serverError.opcode = htons(5);
642 req.serverError.errorcode = htons(2);
643 strcpy(req.serverError.errormessage, "Access violation");
644 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
645 logMess(&req, 1);
646 req.attempt = UCHAR_MAX;
647 continue;
648 }
649
650 if (req.filename[0] == fileSep)
651 req.filename++;
652
653 if (!cfig.homes[0].alias[0])
654 {
655 if (strlen(cfig.homes[0].target) + strlen(req.filename) >= sizeof(req.path))
656 {
657 req.serverError.opcode = htons(5);
658 req.serverError.errorcode = htons(4);
659 sprintf(req.serverError.errormessage, "Filename too large");
660 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
661 logMess(&req, 1);
662 req.attempt = UCHAR_MAX;
663 continue;
664 }
665
666 strcpy(req.path, cfig.homes[0].target);
667 strcat(req.path, req.filename);
668 }
669 else
670 {
671 char *bname = strchr(req.filename, fileSep);
672
673 if (bname)
674 {
675 *bname = 0;
676 bname++;
677 }
678 else
679 {
680 req.serverError.opcode = htons(5);
681 req.serverError.errorcode = htons(2);
682 sprintf(req.serverError.errormessage, "Missing directory/alias");
683 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
684 logMess(&req, 1);
685 req.attempt = UCHAR_MAX;
686 continue;
687 }
688
689 for (int i = 0; i < 8; i++)
690 {
691 //printf("%s=%i\n", req.filename, cfig.homes[i].alias[0]);
692 if (cfig.homes[i].alias[0] && !strcasecmp(req.filename, cfig.homes[i].alias))
693 {
694 if (strlen(cfig.homes[i].target) + strlen(bname) >= sizeof(req.path))
695 {
696 req.serverError.opcode = htons(5);
697 req.serverError.errorcode = htons(4);
698 sprintf(req.serverError.errormessage, "Filename too large");
699 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
700 logMess(&req, 1);
701 req.attempt = UCHAR_MAX;
702 break;
703 }
704
705 strcpy(req.path, cfig.homes[i].target);
706 strcat(req.path, bname);
707 break;
708 }
709 else if (i == 7 || !cfig.homes[i].alias[0])
710 {
711 req.serverError.opcode = htons(5);
712 req.serverError.errorcode = htons(2);
713 sprintf(req.serverError.errormessage, "No such directory/alias %s", req.filename);
714 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
715 logMess(&req, 1);
716 req.attempt = UCHAR_MAX;
717 break;
718 }
719 }
720 }
721
722 if (req.attempt >= 3)
723 continue;
724
725 if (ntohs(req.mesin.opcode) == 1)
726 {
727 if (!cfig.fileRead)
728 {
729 req.serverError.opcode = htons(5);
730 req.serverError.errorcode = htons(2);
731 strcpy(req.serverError.errormessage, "GET Access Denied");
732 logMess(&req, 1);
733 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
734 req.attempt = UCHAR_MAX;
735 continue;
736 }
737
738 if (*inPtr)
739 {
740 char *tmp = inPtr;
741
742 while (*tmp)
743 {
744 if (!strcasecmp(tmp, "blksize"))
745 {
746 tmp += strlen(tmp) + 1;
747 DWORD val = atol(tmp);
748
749 if (val < 512)
750 val = 512;
751 else if (val > blksize)
752 val = blksize;
753
754 req.blksize = val;
755 break;
756 }
757
758 tmp += strlen(tmp) + 1;
759 }
760 }
761
762 errno = 0;
763
764 if (!strcasecmp(req.mode, "netascii") || !strcasecmp(req.mode, "ascii"))
765 req.file = fopen(req.path, "rt");
766 else
767 req.file = fopen(req.path, "rb");
768
769 if (errno || !req.file)
770 {
771 req.serverError.opcode = htons(5);
772 req.serverError.errorcode = htons(1);
773 strcpy(req.serverError.errormessage, "File not found or No Access");
774 logMess(&req, 1);
775 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
776 req.attempt = UCHAR_MAX;
777 continue;
778 }
779
780 setvbuf(req.file, NULL, _IOFBF, req.blksize);
781 }
782 else
783 {
784 if (!cfig.fileWrite && !cfig.fileOverwrite)
785 {
786 req.serverError.opcode = htons(5);
787 req.serverError.errorcode = htons(2);
788 strcpy(req.serverError.errormessage, "PUT Access Denied");
789 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
790 logMess(&req, 1);
791 req.attempt = UCHAR_MAX;
792 continue;
793 }
794
795 req.file = fopen(req.path, "rb");
796
797 if (req.file)
798 {
799 fclose(req.file);
800 req.file = NULL;
801
802 if (!cfig.fileOverwrite)
803 {
804 req.serverError.opcode = htons(5);
805 req.serverError.errorcode = htons(6);
806 strcpy(req.serverError.errormessage, "File already exists");
807 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
808 logMess(&req, 1);
809 req.attempt = UCHAR_MAX;
810 continue;
811 }
812 }
813 else if (!cfig.fileWrite)
814 {
815 req.serverError.opcode = htons(5);
816 req.serverError.errorcode = htons(2);
817 strcpy(req.serverError.errormessage, "Create File Access Denied");
818 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
819 logMess(&req, 1);
820 req.attempt = UCHAR_MAX;
821 continue;
822 }
823
824 errno = 0;
825
826 if (!strcasecmp(req.mode, "netascii") || !strcasecmp(req.mode, "ascii"))
827 req.file = fopen(req.path, "wt");
828 else
829 req.file = fopen(req.path, "wb");
830
831 if (errno || !req.file)
832 {
833 req.serverError.opcode = htons(5);
834 req.serverError.errorcode = htons(2);
835 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
836 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
837 logMess(&req, 1);
838 req.attempt = UCHAR_MAX;
839 continue;
840 }
841 }
842
843 if (*inPtr)
844 {
845 fetchAck = true;
846 char *outPtr = req.mesout.buffer;
847 req.mesout.opcode = htons(6);
848 DWORD val;
849 while (*inPtr)
850 {
851 //printf("%s\n", inPtr);
852 if (!strcasecmp(inPtr, "blksize"))
853 {
854 strcpy(outPtr, inPtr);
855 outPtr += strlen(outPtr) + 1;
856 inPtr += strlen(inPtr) + 1;
857 val = atol(inPtr);
858
859 if (val < 512)
860 val = 512;
861 else if (val > blksize)
862 val = blksize;
863
864 req.blksize = val;
865 sprintf(outPtr, "%lu", val);
866 outPtr += strlen(outPtr) + 1;
867 }
868 else if (!strcasecmp(inPtr, "tsize"))
869 {
870 strcpy(outPtr, inPtr);
871 outPtr += strlen(outPtr) + 1;
872 inPtr += strlen(inPtr) + 1;
873
874 if (ntohs(req.mesin.opcode) == 1)
875 {
876 if (!fseek(req.file, 0, SEEK_END))
877 {
878 if (ftell(req.file) >= 0)
879 {
880 req.tsize = ftell(req.file);
881 sprintf(outPtr, "%lu", req.tsize);
882 outPtr += strlen(outPtr) + 1;
883 }
884 else
885 {
886 req.serverError.opcode = htons(5);
887 req.serverError.errorcode = htons(2);
888 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
889 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
890 logMess(&req, 1);
891 req.attempt = UCHAR_MAX;
892 break;
893 }
894 }
895 else
896 {
897 req.serverError.opcode = htons(5);
898 req.serverError.errorcode = htons(2);
899 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
900 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
901 logMess(&req, 1);
902 req.attempt = UCHAR_MAX;
903 break;
904 }
905 }
906 else
907 {
908 req.tsize = 0;
909 sprintf(outPtr, "%lu", req.tsize);
910 outPtr += strlen(outPtr) + 1;
911 }
912 }
913 else if (!strcasecmp(inPtr, "timeout"))
914 {
915 strcpy(outPtr, inPtr);
916 outPtr += strlen(outPtr) + 1;
917 inPtr += strlen(inPtr) + 1;
918 val = atoi(inPtr);
919
920 if (val < 1)
921 val = 1;
922 else if (val > UCHAR_MAX)
923 val = UCHAR_MAX;
924
925 req.timeout = val;
926 req.expiry = time(NULL) + req.timeout;
927 sprintf(outPtr, "%lu", val);
928 outPtr += strlen(outPtr) + 1;
929 }
930
931 inPtr += strlen(inPtr) + 1;
932 //printf("=%u\n", val);
933 }
934
935 if (req.attempt >= 3)
936 continue;
937
938 errno = 0;
939 req.bytesReady = (DWORD)outPtr - (DWORD)&req.mesout;
940 //printf("Bytes Ready=%u\n", req.bytesReady);
941 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
942 errno = WSAGetLastError();
943 }
944 else if (htons(req.mesin.opcode) == 2)
945 {
946 req.acout.opcode = htons(4);
947 req.acout.block = htons(0);
948 errno = 0;
949 req.bytesReady = 4;
950 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
951 errno = WSAGetLastError();
952 }
953
954 if (errno)
955 {
956 sprintf(req.serverError.errormessage, "Communication Error");
957 logMess(&req, 1);
958 req.attempt = UCHAR_MAX;
959 continue;
960 }
961 else if (ntohs(req.mesin.opcode) == 1)
962 {
963 errno = 0;
964 req.pkt[0] = (packet*)calloc(1, req.blksize + 4);
965 req.pkt[1] = (packet*)calloc(1, req.blksize + 4);
966
967 if (errno || !req.pkt[0] || !req.pkt[1])
968 {
969 sprintf(req.serverError.errormessage, "Memory Error");
970 logMess(&req, 1);
971 req.attempt = UCHAR_MAX;
972 continue;
973 }
974
975 long ftellLoc = ftell(req.file);
976
977 if (ftellLoc > 0)
978 {
979 if (fseek(req.file, 0, SEEK_SET))
980 {
981 req.serverError.opcode = htons(5);
982 req.serverError.errorcode = htons(2);
983 strcpy(req.serverError.errormessage, "File Access Error");
984 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
985 logMess(&req, 1);
986 req.attempt = UCHAR_MAX;
987 continue;
988 }
989 }
990 else if (ftellLoc < 0)
991 {
992 req.serverError.opcode = htons(5);
993 req.serverError.errorcode = htons(2);
994 strcpy(req.serverError.errormessage, "File Access Error");
995 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
996 logMess(&req, 1);
997 req.attempt = UCHAR_MAX;
998 continue;
999 }
1000
1001 errno = 0;
1002 req.pkt[0]->opcode = htons(3);
1003 req.pkt[0]->block = htons(1);
1004 req.bytesRead[0] = fread(&req.pkt[0]->buffer, 1, req.blksize, req.file);
1005
1006 if (errno)
1007 {
1008 req.serverError.opcode = htons(5);
1009 req.serverError.errorcode = htons(2);
1010 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
1011 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1012 logMess(&req, 1);
1013 req.attempt = UCHAR_MAX;
1014 continue;
1015 }
1016
1017 if (req.bytesRead[0] == req.blksize)
1018 {
1019 req.pkt[1]->opcode = htons(3);
1020 req.pkt[1]->block = htons(2);
1021 req.bytesRead[1] = fread(&req.pkt[1]->buffer, 1, req.blksize, req.file);
1022 if (req.bytesRead[1] < req.blksize)
1023 {
1024 fclose(req.file);
1025 req.file = 0;
1026 }
1027 }
1028 else
1029 {
1030 fclose(req.file);
1031 req.file = 0;
1032 }
1033
1034 if (errno)
1035 {
1036 req.serverError.opcode = htons(5);
1037 req.serverError.errorcode = htons(2);
1038 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
1039 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1040 logMess(&req, 1);
1041 req.attempt = UCHAR_MAX;
1042 continue;
1043 }
1044
1045 while (req.attempt <= 3)
1046 {
1047 if (fetchAck)
1048 {
1049 FD_ZERO(&req.readfds);
1050 req.tv.tv_sec = 1;
1051 req.tv.tv_usec = 0;
1052 FD_SET(req.sock, &req.readfds);
1053 select(req.sock + 1, &req.readfds, NULL, NULL, &req.tv);
1054
1055 if (FD_ISSET(req.sock, &req.readfds))
1056 {
1057 errno = 0;
1058 req.bytesRecd = recv(req.sock, (char*)&req.mesin, sizeof(message), 0);
1059 errno = WSAGetLastError();
1060 if (req.bytesRecd <= 0 || errno)
1061 {
1062 sprintf(req.serverError.errormessage, "Communication Error");
1063 logMess(&req, 1);
1064 req.attempt = UCHAR_MAX;
1065 break;
1066 }
1067 else if(req.bytesRecd >= 4 && ntohs(req.mesin.opcode) == 4)
1068 {
1069 if (ntohs(req.acin.block) == req.block)
1070 {
1071 req.block++;
1072 req.fblock++;
1073 req.attempt = 0;
1074 }
1075 else if (req.expiry > time(NULL))
1076 continue;
1077 else
1078 req.attempt++;
1079 }
1080 else if (ntohs(req.mesin.opcode) == 5)
1081 {
1082 sprintf(req.serverError.errormessage, "Client %s:%u, Error Code %i at Client, %s", inet_ntoa(req.client.sin_addr), ntohs(req.client.sin_port), ntohs(req.clientError.errorcode), req.clientError.errormessage);
1083 logMess(&req, 1);
1084 req.attempt = UCHAR_MAX;
1085 break;
1086 }
1087 else
1088 {
1089 req.serverError.opcode = htons(5);
1090 req.serverError.errorcode = htons(4);
1091 sprintf(req.serverError.errormessage, "Unexpected Option Code %i", ntohs(req.mesin.opcode));
1092 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1093 logMess(&req, 1);
1094 req.attempt = UCHAR_MAX;
1095 break;
1096 }
1097 }
1098 else if (req.expiry > time(NULL))
1099 continue;
1100 else
1101 req.attempt++;
1102 }
1103 else
1104 {
1105 fetchAck = true;
1106 req.acin.block = 1;
1107 req.block = 1;
1108 req.fblock = 1;
1109 }
1110
1111 if (req.attempt >= 3)
1112 {
1113 req.serverError.opcode = htons(5);
1114 req.serverError.errorcode = htons(0);
1115
1116 if (req.fblock && !req.block)
1117 strcpy(req.serverError.errormessage, "Large File, Block# Rollover not supported by Client");
1118 else
1119 strcpy(req.serverError.errormessage, "Timeout");
1120
1121 logMess(&req, 1);
1122 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1123 req.attempt = UCHAR_MAX;
1124 break;
1125 }
1126 else if (!req.fblock)
1127 {
1128 errno = 0;
1129 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1130 errno = WSAGetLastError();
1131 if (errno)
1132 {
1133 sprintf(req.serverError.errormessage, "Communication Error");
1134 logMess(&req, 1);
1135 req.attempt = UCHAR_MAX;
1136 break;
1137 }
1138 req.expiry = time(NULL) + req.timeout;
1139 }
1140 else if (ntohs(req.pkt[0]->block) == req.block)
1141 {
1142 errno = 0;
1143 send(req.sock, (const char*)req.pkt[0], req.bytesRead[0] + 4, 0);
1144 errno = WSAGetLastError();
1145 if (errno)
1146 {
1147 sprintf(req.serverError.errormessage, "Communication Error");
1148 logMess(&req, 1);
1149 req.attempt = UCHAR_MAX;
1150 break;
1151 }
1152 req.expiry = time(NULL) + req.timeout;
1153
1154 if (req.file)
1155 {
1156 req.tblock = ntohs(req.pkt[1]->block) + 1;
1157 if (req.tblock == req.block)
1158 {
1159 req.pkt[1]->block = htons(++req.tblock);
1160 req.bytesRead[1] = fread(&req.pkt[1]->buffer, 1, req.blksize, req.file);
1161
1162 if (errno)
1163 {
1164 req.serverError.opcode = htons(5);
1165 req.serverError.errorcode = htons(4);
1166 sprintf(req.serverError.errormessage, strerror(errno));
1167 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1168 logMess(&req, 1);
1169 req.attempt = UCHAR_MAX;
1170 break;
1171 }
1172 else if (req.bytesRead[1] < req.blksize)
1173 {
1174 fclose(req.file);
1175 req.file = 0;
1176 }
1177 }
1178 }
1179 }
1180 else if (ntohs(req.pkt[1]->block) == req.block)
1181 {
1182 errno = 0;
1183 send(req.sock, (const char*)req.pkt[1], req.bytesRead[1] + 4, 0);
1184 errno = WSAGetLastError();
1185 if (errno)
1186 {
1187 sprintf(req.serverError.errormessage, "Communication Error");
1188 logMess(&req, 1);
1189 req.attempt = UCHAR_MAX;
1190 break;
1191 }
1192
1193 req.expiry = time(NULL) + req.timeout;
1194
1195 if (req.file)
1196 {
1197 req.tblock = ntohs(req.pkt[0]->block) + 1;
1198 if (req.tblock == req.block)
1199 {
1200 req.pkt[0]->block = htons(++req.tblock);
1201 req.bytesRead[0] = fread(&req.pkt[0]->buffer, 1, req.blksize, req.file);
1202 if (errno)
1203 {
1204 req.serverError.opcode = htons(5);
1205 req.serverError.errorcode = htons(4);
1206 sprintf(req.serverError.errormessage, strerror(errno));
1207 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1208 logMess(&req, 1);
1209 req.attempt = UCHAR_MAX;
1210 break;
1211 }
1212 else if (req.bytesRead[0] < req.blksize)
1213 {
1214 fclose(req.file);
1215 req.file = 0;
1216 }
1217 }
1218 }
1219 }
1220 else
1221 {
1222 sprintf(req.serverError.errormessage, "%lu Blocks Served", req.fblock - 1);
1223 logMess(&req, 2);
1224 req.attempt = UCHAR_MAX;
1225 break;
1226 }
1227 }
1228 }
1229 else if (ntohs(req.mesin.opcode) == 2)
1230 {
1231 errno = 0;
1232 req.pkt[0] = (packet*)calloc(1, req.blksize + 4);
1233
1234 if (errno || !req.pkt[0])
1235 {
1236 sprintf(req.serverError.errormessage, "Memory Error");
1237 logMess(&req, 1);
1238 req.attempt = UCHAR_MAX;
1239 continue;
1240 }
1241
1242 while (req.attempt <= 3)
1243 {
1244 FD_ZERO(&req.readfds);
1245 req.tv.tv_sec = 1;
1246 req.tv.tv_usec = 0;
1247 FD_SET(req.sock, &req.readfds);
1248 select(req.sock + 1, &req.readfds, NULL, NULL, &req.tv);
1249
1250 if (FD_ISSET(req.sock, &req.readfds))
1251 {
1252 errno = 0;
1253 req.bytesRecd = recv(req.sock, (char*)req.pkt[0], req.blksize + 4, 0);
1254 errno = WSAGetLastError();
1255
1256 if (errno)
1257 {
1258 sprintf(req.serverError.errormessage, "Communication Error");
1259 logMess(&req, 1);
1260 req.attempt = UCHAR_MAX;
1261 break;
1262 }
1263 }
1264 else
1265 req.bytesRecd = 0;
1266
1267 if (req.bytesRecd >= 4)
1268 {
1269 if (ntohs(req.pkt[0]->opcode) == 3)
1270 {
1271 req.tblock = req.block + 1;
1272
1273 if (ntohs(req.pkt[0]->block) == req.tblock)
1274 {
1275 req.acout.opcode = htons(4);
1276 req.acout.block = req.pkt[0]->block;
1277 req.block++;
1278 req.fblock++;
1279 req.bytesReady = 4;
1280 req.expiry = time(NULL) + req.timeout;
1281
1282 errno = 0;
1283 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1284 errno = WSAGetLastError();
1285
1286 if (errno)
1287 {
1288 sprintf(req.serverError.errormessage, "Communication Error");
1289 logMess(&req, 1);
1290 req.attempt = UCHAR_MAX;
1291 break;
1292 }
1293
1294 if (req.bytesRecd > 4)
1295 {
1296 errno = 0;
1297 if (fwrite(&req.pkt[0]->buffer, req.bytesRecd - 4, 1, req.file) != 1 || errno)
1298 {
1299 req.serverError.opcode = htons(5);
1300 req.serverError.errorcode = htons(3);
1301 strcpy(req.serverError.errormessage, "Disk full or allocation exceeded");
1302 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1303 logMess(&req, 1);
1304 req.attempt = UCHAR_MAX;
1305 break;
1306 }
1307 else
1308 req.attempt = 0;
1309 }
1310 else
1311 req.attempt = 0;
1312
1313 if ((WORD)req.bytesRecd < req.blksize + 4)
1314 {
1315 fclose(req.file);
1316 req.file = 0;
1317 sprintf(req.serverError.errormessage, "%lu Blocks Received", req.fblock);
1318 logMess(&req, 2);
1319 req.attempt = UCHAR_MAX;
1320 break;
1321 }
1322 }
1323 else if (req.expiry > time(NULL))
1324 continue;
1325 else if (req.attempt >= 3)
1326 {
1327 req.serverError.opcode = htons(5);
1328 req.serverError.errorcode = htons(0);
1329
1330 if (req.fblock && !req.block)
1331 strcpy(req.serverError.errormessage, "Large File, Block# Rollover not supported by Client");
1332 else
1333 strcpy(req.serverError.errormessage, "Timeout");
1334
1335 logMess(&req, 1);
1336 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1337 req.attempt = UCHAR_MAX;
1338 break;
1339 }
1340 else
1341 {
1342 req.expiry = time(NULL) + req.timeout;
1343 errno = 0;
1344 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1345 errno = WSAGetLastError();
1346 req.attempt++;
1347
1348 if (errno)
1349 {
1350 sprintf(req.serverError.errormessage, "Communication Error");
1351 logMess(&req, 1);
1352 req.attempt = UCHAR_MAX;
1353 break;
1354 }
1355 }
1356 }
1357 else if (req.bytesRecd > (int)sizeof(message))
1358 {
1359 req.serverError.opcode = htons(5);
1360 req.serverError.errorcode = htons(4);
1361 sprintf(req.serverError.errormessage, "Error: Incoming Packet too large");
1362 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1363 logMess(&req, 1);
1364 req.attempt = UCHAR_MAX;
1365 break;
1366 }
1367 else if (ntohs(req.pkt[0]->opcode) == 5)
1368 {
1369 sprintf(req.serverError.errormessage, "Error Code %i at Client, %s", ntohs(req.pkt[0]->block), &req.pkt[0]->buffer);
1370 logMess(&req, 1);
1371 req.attempt = UCHAR_MAX;
1372 break;
1373 }
1374 else
1375 {
1376 req.serverError.opcode = htons(5);
1377 req.serverError.errorcode = htons(4);
1378 sprintf(req.serverError.errormessage, "Unexpected Option Code %i", ntohs(req.pkt[0]->opcode));
1379 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1380 logMess(&req, 1);
1381 req.attempt = UCHAR_MAX;
1382 break;
1383 }
1384 }
1385 else if (req.expiry > time(NULL))
1386 continue;
1387 else if (req.attempt >= 3)
1388 {
1389 req.serverError.opcode = htons(5);
1390 req.serverError.errorcode = htons(0);
1391
1392 if (req.fblock && !req.block)
1393 strcpy(req.serverError.errormessage, "Large File, Block# Rollover not supported by Client");
1394 else
1395 strcpy(req.serverError.errormessage, "Timeout");
1396
1397 logMess(&req, 1);
1398 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1399 req.attempt = UCHAR_MAX;
1400 break;
1401 }
1402 else
1403 {
1404 req.expiry = time(NULL) + req.timeout;
1405 errno = 0;
1406 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1407 errno = WSAGetLastError();
1408 req.attempt++;
1409
1410 if (errno)
1411 {
1412 sprintf(req.serverError.errormessage, "Communication Error");
1413 logMess(&req, 1);
1414 req.attempt = UCHAR_MAX;
1415 break;
1416 }
1417 }
1418 }
1419 }
1420 }
1421 while (cleanReq(&req));
1422
1423 WaitForSingleObject(cEvent, INFINITE);
1424 totalThreads--;
1425 SetEvent(cEvent);
1426
1427 //printf("Thread %u Killed\n",GetCurrentThreadId());
1428 _endthread();
1429 return;
1430 }
1431
1432 bool cleanReq(request* req)
1433 {
1434 //printf("cleaning\n");
1435
1436 if (req->file)
1437 fclose(req->file);
1438
1439 if (!(req->sock == INVALID_SOCKET))
1440 {
1441 //printf("Here\n");
1442 closesocket(req->sock);
1443 }
1444
1445 if (req->pkt[0])
1446 free(req->pkt[0]);
1447
1448 if (req->pkt[1])
1449 free(req->pkt[1]);
1450
1451 WaitForSingleObject(cEvent, INFINITE);
1452 activeThreads--;
1453 SetEvent(cEvent);
1454
1455 //printf("cleaned\n");
1456
1457 return (totalThreads <= minThreads);
1458 }
1459
1460 char* myGetToken(char* buff, BYTE index)
1461 {
1462 while (*buff)
1463 {
1464 if (index)
1465 index--;
1466 else
1467 break;
1468
1469 buff += strlen(buff) + 1;
1470 }
1471
1472 return buff;
1473 }
1474
1475 WORD myTokenize(char *target, char *source, char *sep, bool whiteSep)
1476 {
1477 bool found = true;
1478 char *dp = target;
1479 WORD kount = 0;
1480
1481 while (*source)
1482 {
1483 if (sep && sep[0] && strchr(sep, (*source)))
1484 {
1485 found = true;
1486 source++;
1487 continue;
1488 }
1489 else if (whiteSep && *source <= 32)
1490 {
1491 found = true;
1492 source++;
1493 continue;
1494 }
1495
1496 if (found)
1497 {
1498 if (target != dp)
1499 {
1500 *dp = 0;
1501 dp++;
1502 }
1503 kount++;
1504 }
1505
1506 found = false;
1507 *dp = *source;
1508 dp++;
1509 source++;
1510 }
1511
1512 *dp = 0;
1513 dp++;
1514 *dp = 0;
1515
1516 //printf("%s\n", target);
1517
1518 return kount;
1519 }
1520
1521 char* myTrim(char *target, char *source)
1522 {
1523 while ((*source) && (*source) <= 32)
1524 source++;
1525
1526 int i = 0;
1527
1528 for (; i < 511 && source[i]; i++)
1529 target[i] = source[i];
1530
1531 target[i] = source[i];
1532 i--;
1533
1534 for (; i >= 0 && target[i] <= 32; i--)
1535 target[i] = 0;
1536
1537 return target;
1538 }
1539
1540 void mySplit(char *name, char *value, char *source, char splitChar)
1541 {
1542 int i = 0;
1543 int j = 0;
1544 int k = 0;
1545
1546 for (; source[i] && j <= 510 && source[i] != splitChar; i++, j++)
1547 {
1548 name[j] = source[i];
1549 }
1550
1551 if (source[i])
1552 {
1553 i++;
1554 for (; k <= 510 && source[i]; i++, k++)
1555 {
1556 value[k] = source[i];
1557 }
1558 }
1559
1560 name[j] = 0;
1561 value[k] = 0;
1562
1563 myTrim(name, name);
1564 myTrim(value, value);
1565 //printf("%s %s\n", name, value);
1566 }
1567
1568 bool getSection(char *sectionName, char *buffer, BYTE serial, char *fileName)
1569 {
1570 //printf("%s=%s\n",fileName,sectionName);
1571 char section[128];
1572 sprintf(section, "[%s]", sectionName);
1573 myUpper(section);
1574 FILE *f = fopen(fileName, "rt");
1575 char buff[512];
1576 BYTE found = 0;
1577
1578 if (f)
1579 {
1580 while (fgets(buff, 511, f))
1581 {
1582 myUpper(buff);
1583 myTrim(buff, buff);
1584
1585 if (strstr(buff, section) == buff)
1586 {
1587 found++;
1588 if (found == serial)
1589 {
1590 //printf("%s=%s\n",fileName,sectionName);
1591 while (fgets(buff, 511, f))
1592 {
1593 myTrim(buff, buff);
1594
1595 if (strstr(buff, "[") == buff)
1596 break;
1597
1598 if ((*buff) >= '0' && (*buff) <= '9' || (*buff) >= 'A' && (*buff) <= 'Z' || (*buff) >= 'a' && (*buff) <= 'z' || ((*buff) && strchr("/\\?*", (*buff))))
1599 {
1600 buffer += sprintf(buffer, "%s", buff);
1601 buffer++;
1602 }
1603 }
1604 break;
1605 }
1606 }
1607 }
1608 fclose(f);
1609 }
1610
1611 *buffer = 0;
1612 *(buffer + 1) = 0;
1613 return (found == serial);
1614 }
1615
1616 char *IP2String(char *target, DWORD ip)
1617 {
1618 data15 inaddr;
1619 inaddr.ip = ip;
1620 sprintf(target, "%u.%u.%u.%u", inaddr.octate[0], inaddr.octate[1], inaddr.octate[2], inaddr.octate[3]);
1621 return target;
1622 }
1623
1624 bool isIP(char *string)
1625 {
1626 int j = 0;
1627
1628 for (; *string; string++)
1629 {
1630 if (*string == '.' && *(string + 1) != '.')
1631 j++;
1632 else if (*string < '0' || *string > '9')
1633 return 0;
1634 }
1635
1636 if (j == 3)
1637 return 1;
1638 else
1639 return 0;
1640 }
1641
1642 char *myUpper(char *string)
1643 {
1644 char diff = 'a' - 'A';
1645 WORD len = strlen(string);
1646 for (int i = 0; i < len; i++)
1647 if (string[i] >= 'a' && string[i] <= 'z')
1648 string[i] -= diff;
1649 return string;
1650 }
1651
1652 char *myLower(char *string)
1653 {
1654 char diff = 'a' - 'A';
1655 WORD len = strlen(string);
1656 for (int i = 0; i < len; i++)
1657 if (string[i] >= 'A' && string[i] <= 'Z')
1658 string[i] += diff;
1659 return string;
1660 }
1661
1662 void init()
1663 {
1664 memset(&cfig, 0, sizeof(cfig));
1665
1666 GetModuleFileName(NULL, iniFile, MAX_PATH);
1667 char *iniFileExt = strrchr(iniFile, '.');
1668 strcpy(iniFileExt, ".ini");
1669 GetModuleFileName(NULL, logFile, MAX_PATH);
1670 iniFileExt = strrchr(logFile, '.');
1671 strcpy(iniFileExt, ".log");
1672
1673 char iniStr[4096];
1674 char name[256];
1675 char value[256];
1676
1677 if (verbatim)
1678 {
1679 cfig.logLevel = 2;
1680 printf("%s\n\n", sVersion);
1681 }
1682 else if (getSection("LOGGING", iniStr, 1, iniFile))
1683 {
1684 char *iniStrPtr = myGetToken(iniStr, 0);
1685
1686 if (!iniStrPtr[0] || !strcasecmp(iniStrPtr, "None"))
1687 cfig.logLevel = 0;
1688 else if (!strcasecmp(iniStrPtr, "Errors"))
1689 cfig.logLevel = 1;
1690 else if (!strcasecmp(iniStrPtr, "All"))
1691 cfig.logLevel = 2;
1692 else if (!strcasecmp(iniStrPtr, "Debug"))
1693 cfig.logLevel = 3;
1694 else
1695 cfig.logLevel = UCHAR_MAX;
1696 }
1697
1698 if (!verbatim && cfig.logLevel)
1699 {
1700 cfig.logfile = fopen(logFile, "wt");
1701
1702 if (cfig.logfile)
1703 {
1704 fclose(cfig.logfile);
1705 cfig.logfile = fopen(logFile, "at");
1706 fprintf(cfig.logfile, "%s\n", sVersion);
1707 }
1708 }
1709
1710 if (cfig.logLevel == UCHAR_MAX)
1711 {
1712 cfig.logLevel = 1;
1713 sprintf(logBuff, "Section [LOGGING], Invalid Logging Level: %s, ignored", myGetToken(iniStr, 0));
1714 logMess(logBuff, 1);
1715 }
1716
1717 WORD wVersionRequested = MAKEWORD(1, 1);
1718 WSAStartup(wVersionRequested, &cfig.wsaData);
1719
1720 if (cfig.wsaData.wVersion != wVersionRequested)
1721 {
1722 sprintf(logBuff, "WSAStartup Error");
1723 logMess(logBuff, 1);
1724 }
1725
1726 if (getSection("LISTEN-ON", iniStr, 1, iniFile))
1727 {
1728 char *iniStrPtr = myGetToken(iniStr, 0);
1729
1730 for (int i = 0; i < MAX_SERVERS && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1))
1731 {
1732 strncpy(name, iniStrPtr, UCHAR_MAX);
1733 WORD port = 69;
1734 char *dp = strchr(name, ':');
1735 if (dp)
1736 {
1737 *dp = 0;
1738 dp++;
1739 port = atoi(dp);
1740 }
1741
1742 DWORD ip = my_inet_addr(name);
1743
1744 if (isIP(name) && ip)
1745 {
1746 for (BYTE j = 0; j < MAX_SERVERS; j++)
1747 {
1748 if (cfig.servers[j] == ip)
1749 break;
1750 else if (!cfig.servers[j])
1751 {
1752 cfig.servers[j] = ip;
1753 cfig.ports[j] = port;
1754 i++;
1755 break;
1756 }
1757 }
1758 }
1759 else
1760 {
1761 sprintf(logBuff, "Warning: Section [LISTEN-ON], Invalid IP Address %s, ignored", iniStrPtr);
1762 logMess(logBuff, 1);
1763 }
1764 }
1765 }
1766
1767 if (getSection("HOME", iniStr, 1, iniFile))
1768 {
1769 char *iniStrPtr = myGetToken(iniStr, 0);
1770 for (; iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1))
1771 {
1772 mySplit(name, value, iniStrPtr, '=');
1773 if (strlen(value))
1774 {
1775 if (!cfig.homes[0].alias[0] && cfig.homes[0].target[0])
1776 {
1777 sprintf(logBuff, "Section [HOME], alias and bare path mixup, entry %s ignored", iniStrPtr);
1778 logMess(logBuff, 1);
1779 }
1780 else if (strchr(name, notFileSep) || strchr(name, fileSep) || strchr(name, '>') || strchr(name, '<') || strchr(name, '.'))
1781 {
1782 sprintf(logBuff, "Section [HOME], invalid chars in alias %s, entry ignored", name);
1783 logMess(logBuff, 1);
1784 }
1785 else if (name[0] && strlen(name) < 64 && value[0])
1786 {
1787 for (int i = 0; i < 8; i++)
1788 {
1789 if (cfig.homes[i].alias[0] && !strcasecmp(name, cfig.homes[i].alias))
1790 {
1791 sprintf(logBuff, "Section [HOME], Duplicate Entry: %s ignored", iniStrPtr);
1792 logMess(logBuff, 1);
1793 break;
1794 }
1795 else if (!cfig.homes[i].alias[0])
1796 {
1797 strcpy(cfig.homes[i].alias, name);
1798 strcpy(cfig.homes[i].target, value);
1799
1800 if (cfig.homes[i].target[strlen(cfig.homes[i].target) - 1] != fileSep)
1801 {
1802 tempbuff[0] = fileSep;
1803 tempbuff[1] = 0;
1804 strcat(cfig.homes[i].target, tempbuff);
1805 }
1806
1807 break;
1808 }
1809 }
1810 }
1811 else
1812 {
1813 sprintf(logBuff, "Section [HOME], alias %s too large", name);
1814 logMess(logBuff, 1);
1815 }
1816 }
1817 else if (!cfig.homes[0].alias[0] && !cfig.homes[0].target[0])
1818 {
1819 strcpy(cfig.homes[0].target, name);
1820
1821 if (cfig.homes[0].target[strlen(cfig.homes[0].target) - 1] != fileSep)
1822 {
1823 tempbuff[0] = fileSep;
1824 tempbuff[1] = 0;
1825 strcat(cfig.homes[0].target, tempbuff);
1826 }
1827 }
1828 else if (cfig.homes[0].alias[0])
1829 {
1830 sprintf(logBuff, "Section [HOME], alias and bare path mixup, entry %s ignored", iniStrPtr);
1831 logMess(logBuff, 1);
1832 }
1833 else if (cfig.homes[0].target[0])
1834 {
1835 sprintf(logBuff, "Section [HOME], Duplicate Path: %s ignored", iniStrPtr);
1836 logMess(logBuff, 1);
1837 }
1838 else
1839 {
1840 sprintf(logBuff, "Section [HOME], missing = sign, Invalid Entry: %s ignored", iniStrPtr);
1841 logMess(logBuff, 1);
1842 }
1843 }
1844 }
1845
1846 if (!cfig.homes[0].target[0])
1847 {
1848 GetModuleFileName(NULL, cfig.homes[0].target, UCHAR_MAX);
1849 char *iniFileExt = strrchr(cfig.homes[0].target, fileSep);
1850 *(++iniFileExt) = 0;
1851 }
1852
1853 cfig.fileRead = true;
1854
1855 if (getSection("TFTP-OPTIONS", iniStr, 1, iniFile))
1856 {
1857 char *iniStrPtr = myGetToken(iniStr, 0);
1858 for (;strlen(iniStrPtr);iniStrPtr = myGetToken(iniStrPtr, 1))
1859 {
1860 mySplit(name, value, iniStrPtr, '=');
1861 if (strlen(value))
1862 {
1863 if (!strcasecmp(name, "blksize"))
1864 {
1865 DWORD tblksize = atol(value);
1866
1867 if (tblksize < 512)
1868 blksize = 512;
1869 else if (tblksize > USHRT_MAX - 32)
1870 blksize = USHRT_MAX - 32;
1871 else
1872 blksize = tblksize;
1873 }
1874 else if (!strcasecmp(name, "threadpoolsize"))
1875 {
1876 minThreads = atol(value);
1877 if (minThreads < 1)
1878 minThreads = 0;
1879 else if (minThreads > 100)
1880 minThreads = 100;
1881 }
1882 else if (!strcasecmp(name, "timeout"))
1883 {
1884 timeout = atol(value);
1885 if (timeout < 1)
1886 timeout = 1;
1887 else if (timeout > UCHAR_MAX)
1888 timeout = UCHAR_MAX;
1889 }
1890 else if (!strcasecmp(name, "Read"))
1891 {
1892 if (strchr("Yy", *value))
1893 cfig.fileRead = true;
1894 else
1895 cfig.fileRead = false;
1896 }
1897 else if (!strcasecmp(name, "Write"))
1898 {
1899 if (strchr("Yy", *value))
1900 cfig.fileWrite = true;
1901 else
1902 cfig.fileWrite = false;
1903 }
1904 else if (!strcasecmp(name, "Overwrite"))
1905 {
1906 if (strchr("Yy", *value))
1907 cfig.fileOverwrite = true;
1908 else
1909 cfig.fileOverwrite = false;
1910 }
1911 else if (!strcasecmp(name, "port-range"))
1912 {
1913 char *ptr = strchr(value, '-');
1914 if (ptr)
1915 {
1916 *ptr = 0;
1917 cfig.minport = atol(value);
1918 cfig.maxport = atol(++ptr);
1919
1920 if (cfig.minport < 1024 || cfig.minport >= USHRT_MAX || cfig.maxport < 1024 || cfig.maxport >= USHRT_MAX || cfig.minport > cfig.maxport)
1921 {
1922 cfig.minport = 0;
1923 cfig.maxport = 0;
1924
1925 sprintf(logBuff, "Invalid port range %s", value);
1926 logMess(logBuff, 1);
1927 }
1928 }
1929 else
1930 {
1931 sprintf(logBuff, "Invalid port range %s", value);
1932 logMess(logBuff, 1);
1933 }
1934 }
1935 else
1936 {
1937 sprintf(logBuff, "Warning: unknown option %s, ignored", name);
1938 logMess(logBuff, 1);
1939 }
1940 }
1941 }
1942 }
1943
1944 if (getSection("ALLOWED-CLIENTS", iniStr, 1, iniFile))
1945 {
1946 char *iniStrPtr = myGetToken(iniStr, 0);
1947 for (int i = 0; i < 32 && iniStrPtr[0]; iniStrPtr = myGetToken(iniStrPtr, 1))
1948 {
1949 DWORD rs = 0;
1950 DWORD re = 0;
1951 mySplit(name, value, iniStrPtr, '-');
1952 rs = htonl(my_inet_addr(name));
1953
1954 if (strlen(value))
1955 re = htonl(my_inet_addr(value));
1956 else
1957 re = rs;
1958
1959 if (rs && rs != INADDR_NONE && re && re != INADDR_NONE && rs <= re)
1960 {
1961 cfig.hostRanges[i].rangeStart = rs;
1962 cfig.hostRanges[i].rangeEnd = re;
1963 i++;
1964 }
1965 else
1966 {
1967 sprintf(logBuff, "Section [ALLOWED-CLIENTS] Invalid entry %s in ini file, ignored", iniStrPtr);
1968 logMess(logBuff, 1);
1969 }
1970 }
1971 }
1972
1973 // if (!cfig.servers[0])
1974 // getServ();
1975
1976 int i = 0;
1977
1978 for (int j = 0; j < MAX_SERVERS; j++)
1979 {
1980 if (j && !cfig.servers[j])
1981 break;
1982
1983 cfig.tftpConn[i].sock = socket(PF_INET,
1984 SOCK_DGRAM,
1985 IPPROTO_UDP);
1986
1987 if (cfig.tftpConn[i].sock == INVALID_SOCKET)
1988 {
1989 sprintf(logBuff, "Failed to Create Socket");
1990 logMess(logBuff, 1);
1991 continue;
1992 }
1993
1994 cfig.tftpConn[i].addr.sin_family = AF_INET;
1995
1996 if (!cfig.ports[j])
1997 cfig.ports[j] = 69;
1998
1999 cfig.tftpConn[i].addr.sin_addr.s_addr = cfig.servers[j];
2000 cfig.tftpConn[i].addr.sin_port = htons(cfig.ports[j]);
2001
2002 socklen_t nRet = bind(cfig.tftpConn[i].sock,
2003 (sockaddr*)&cfig.tftpConn[i].addr,
2004 sizeof(struct sockaddr_in)
2005 );
2006
2007 if (nRet == SOCKET_ERROR)
2008 {
2009 closesocket(cfig.tftpConn[i].sock);
2010 sprintf(logBuff, "%s Port %u, bind failed", IP2String(tempbuff, cfig.servers[j]), cfig.ports[j]);
2011 logMess(logBuff, 1);
2012 continue;
2013 }
2014
2015 if (cfig.maxFD < cfig.tftpConn[i].sock)
2016 cfig.maxFD = cfig.tftpConn[i].sock;
2017
2018 cfig.tftpConn[i].server = cfig.tftpConn[i].addr.sin_addr.s_addr;
2019 cfig.tftpConn[i].port = htons(cfig.tftpConn[i].addr.sin_port);
2020 i++;
2021 }
2022
2023 cfig.maxFD++;
2024
2025 if (!cfig.tftpConn[0].port)
2026 {
2027 sprintf(logBuff, "no listening interfaces available, stopping..\nPress Enter to exit\n");
2028 logMess(logBuff, 1);
2029 getchar();
2030 exit(-1);
2031 }
2032 else if (verbatim)
2033 {
2034 printf("starting TFTP...\n");
2035 }
2036 else
2037 {
2038 sprintf(logBuff, "starting TFTP service");
2039 logMess(logBuff, 1);
2040 }
2041
2042 for (int i = 0; i < MAX_SERVERS; i++)
2043 if (cfig.homes[i].target[0])
2044 {
2045 sprintf(logBuff, "alias /%s is mapped to %s", cfig.homes[i].alias, cfig.homes[i].target);
2046 logMess(logBuff, 1);
2047 }
2048
2049 if (cfig.hostRanges[0].rangeStart)
2050 {
2051 char temp[128];
2052
2053 for (WORD i = 0; i <= sizeof(cfig.hostRanges) && cfig.hostRanges[i].rangeStart; i++)
2054 {
2055 sprintf(logBuff, "%s", "permitted clients: ");
2056 sprintf(temp, "%s-", IP2String(tempbuff, htonl(cfig.hostRanges[i].rangeStart)));
2057 strcat(logBuff, temp);
2058 sprintf(temp, "%s", IP2String(tempbuff, htonl(cfig.hostRanges[i].rangeEnd)));
2059 strcat(logBuff, temp);
2060 logMess(logBuff, 1);
2061 }
2062 }
2063 else
2064 {
2065 sprintf(logBuff, "%s", "permitted clients: all");
2066 logMess(logBuff, 1);
2067 }
2068
2069 if (cfig.minport)
2070 {
2071 sprintf(logBuff, "server port range: %u-%u", cfig.minport, cfig.maxport);
2072 logMess(logBuff, 1);
2073 }
2074 else
2075 {
2076 sprintf(logBuff, "server port range: all");
2077 logMess(logBuff, 1);
2078 }
2079
2080 sprintf(logBuff, "max blksize: %u", blksize);
2081 logMess(logBuff, 1);
2082 sprintf(logBuff, "default blksize: %u", 512);
2083 logMess(logBuff, 1);
2084 sprintf(logBuff, "default timeout: %u", timeout);
2085 logMess(logBuff, 1);
2086 sprintf(logBuff, "file read allowed: %s", cfig.fileRead ? "Yes" : "No");
2087 logMess(logBuff, 1);
2088 sprintf(logBuff, "file create allowed: %s", cfig.fileWrite ? "Yes" : "No");
2089 logMess(logBuff, 1);
2090 sprintf(logBuff, "file overwrite allowed: %s", cfig.fileOverwrite ? "Yes" : "No");
2091 logMess(logBuff, 1);
2092
2093 if (!verbatim)
2094 {
2095 sprintf(logBuff, "logging: %s", cfig.logLevel > 1 ? "all" : "errors");
2096 logMess(logBuff, 1);
2097 }
2098
2099 lEvent = CreateEvent(
2100 NULL, // default security descriptor
2101 FALSE, // ManualReset
2102 TRUE, // Signalled
2103 TEXT("AchalTFTServerLogEvent")); // object name
2104
2105 if (lEvent == NULL)
2106 {
2107 printf("CreateEvent error: %lu\n", GetLastError());
2108 exit(-1);
2109 }
2110 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2111 {
2112 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2113 logMess(logBuff, 0);
2114 exit(-1);
2115 }
2116
2117 tEvent = CreateEvent(
2118 NULL, // default security descriptor
2119 FALSE, // ManualReset
2120 FALSE, // Signalled
2121 TEXT("AchalTFTServerThreadEvent")); // object name
2122
2123 if (tEvent == NULL)
2124 {
2125 printf("CreateEvent error: %lu\n", GetLastError());
2126 exit(-1);
2127 }
2128 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2129 {
2130 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2131 logMess(logBuff, 0);
2132 exit(-1);
2133 }
2134
2135 sEvent = CreateEvent(
2136 NULL, // default security descriptor
2137 FALSE, // ManualReset
2138 TRUE, // Signalled
2139 TEXT("AchalTFTServerSocketEvent")); // object name
2140
2141 if (sEvent == NULL)
2142 {
2143 printf("CreateEvent error: %lu\n", GetLastError());
2144 exit(-1);
2145 }
2146 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2147 {
2148 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2149 logMess(logBuff, 0);
2150 exit(-1);
2151 }
2152
2153 cEvent = CreateEvent(
2154 NULL, // default security descriptor
2155 FALSE, // ManualReset
2156 TRUE, // Signalled
2157 TEXT("AchalTFTServerCountEvent")); // object name
2158
2159 if (cEvent == NULL)
2160 {
2161 printf("CreateEvent error: %lu\n", GetLastError());
2162 exit(-1);
2163 }
2164 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2165 {
2166 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2167 logMess(logBuff, 0);
2168 exit(-1);
2169 }
2170
2171 if (minThreads)
2172 {
2173 for (int i = 0; i < minThreads; i++)
2174 {
2175 _beginthread(
2176 processRequest, // thread function
2177 0, // default security attributes
2178 NULL); // argument to thread function
2179 }
2180
2181 sprintf(logBuff, "thread pool size: %u", minThreads);
2182 logMess(logBuff, 1);
2183 }
2184
2185 for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].port; i++)
2186 {
2187 sprintf(logBuff, "listening on: %s:%i", IP2String(tempbuff, cfig.tftpConn[i].server), cfig.tftpConn[i].port);
2188 logMess(logBuff, 1);
2189 }
2190 }
2191
2192 void logMess(char *logBuff, BYTE logLevel)
2193 {
2194 WaitForSingleObject(lEvent, INFINITE);
2195
2196 if (verbatim)
2197 printf("%s\n", logBuff);
2198 else if (cfig.logfile && logLevel <= cfig.logLevel)
2199 {
2200 char currentTime[32];
2201 time_t t = time(NULL);
2202 tm *ttm = localtime(&t);
2203 strftime(currentTime, sizeof(currentTime), "%d-%b-%y %X", ttm);
2204 fprintf(cfig.logfile, "[%s] %s\n", currentTime, logBuff);
2205 fflush(cfig.logfile);
2206 }
2207 SetEvent(lEvent);
2208 }
2209
2210 void logMess(request *req, BYTE logLevel)
2211 {
2212 WaitForSingleObject(lEvent, INFINITE);
2213
2214 char tempbuff[256];
2215
2216 if (verbatim)
2217 {
2218 if (!req->serverError.errormessage[0])
2219 sprintf(req->serverError.errormessage, strerror(errno));
2220
2221 if (req->path[0])
2222 printf("Client %s:%u %s, %s\n", IP2String(tempbuff, req->client.sin_addr.s_addr), ntohs(req->client.sin_port), req->path, req->serverError.errormessage);
2223 else
2224 printf("Client %s:%u, %s\n", IP2String(tempbuff, req->client.sin_addr.s_addr), ntohs(req->client.sin_port), req->serverError.errormessage);
2225 }
2226 else if (cfig.logfile && logLevel <= cfig.logLevel)
2227 {
2228 char currentTime[32];
2229 time_t t = time(NULL);
2230 tm *ttm = localtime(&t);
2231 strftime(currentTime, sizeof(currentTime), "%d-%b-%y %X", ttm);
2232
2233 if (req->path[0])
2234 fprintf(cfig.logfile, "[%s] Client %s:%u %s, %s\n", currentTime, IP2String(tempbuff, req->client.sin_addr.s_addr), ntohs(req->client.sin_port), req->path, req->serverError.errormessage);
2235 else
2236 fprintf(cfig.logfile, "[%s] Client %s:%u, %s\n", currentTime, IP2String(tempbuff, req->client.sin_addr.s_addr), ntohs(req->client.sin_port), req->serverError.errormessage);
2237
2238 fflush(cfig.logfile);
2239 }
2240 SetEvent(lEvent);
2241 }