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