[CRT] Massively improve performance of rand_s
[reactos.git] / base / services / tftpd / tftpd.cpp
1 /**************************************************************************
2 * Copyright (C) 2005 by Achal Dhir *
3 * achaldhir@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 // TFTPServer.cpp
21
22 #include <stdio.h>
23 #include <winsock2.h>
24 #include <process.h>
25 #include <time.h>
26 #include <tchar.h>
27 #include <ws2tcpip.h>
28 #include <limits.h>
29 #include <iphlpapi.h>
30 #include <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 }