[TFTPD] Fix bound checks for array cfig.hostRanges. Spotted by 'mudhead'.
[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[256];
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 (int 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 for (int i = 0; i < 8; i++)
759 {
760 //printf("%s=%i\n", req.filename, cfig.homes[i].alias[0]);
761 if (cfig.homes[i].alias[0] && !strcasecmp(req.filename, cfig.homes[i].alias))
762 {
763 if (strlen(cfig.homes[i].target) + strlen(bname) >= sizeof(req.path))
764 {
765 req.serverError.opcode = htons(5);
766 req.serverError.errorcode = htons(4);
767 sprintf(req.serverError.errormessage, "Filename too large");
768 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
769 logMess(&req, 1);
770 req.attempt = UCHAR_MAX;
771 break;
772 }
773
774 strcpy(req.path, cfig.homes[i].target);
775 strcat(req.path, bname);
776 break;
777 }
778 else if (i == 7 || !cfig.homes[i].alias[0])
779 {
780 req.serverError.opcode = htons(5);
781 req.serverError.errorcode = htons(2);
782 sprintf(req.serverError.errormessage, "No such directory/alias %s", req.filename);
783 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
784 logMess(&req, 1);
785 req.attempt = UCHAR_MAX;
786 break;
787 }
788 }
789 }
790
791 if (req.attempt >= 3)
792 continue;
793
794 if (ntohs(req.mesin.opcode) == 1)
795 {
796 if (!cfig.fileRead)
797 {
798 req.serverError.opcode = htons(5);
799 req.serverError.errorcode = htons(2);
800 strcpy(req.serverError.errormessage, "GET Access Denied");
801 logMess(&req, 1);
802 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
803 req.attempt = UCHAR_MAX;
804 continue;
805 }
806
807 if (*inPtr)
808 {
809 char *tmp = inPtr;
810
811 while (*tmp)
812 {
813 if (!strcasecmp(tmp, "blksize"))
814 {
815 tmp += strlen(tmp) + 1;
816 MYDWORD val = atol(tmp);
817
818 if (val < 512)
819 val = 512;
820 else if (val > blksize)
821 val = blksize;
822
823 req.blksize = val;
824 break;
825 }
826
827 tmp += strlen(tmp) + 1;
828 }
829 }
830
831 errno = 0;
832
833 if (!strcasecmp(req.mode, "netascii") || !strcasecmp(req.mode, "ascii"))
834 req.file = fopen(req.path, "rt");
835 else
836 req.file = fopen(req.path, "rb");
837
838 if (errno || !req.file)
839 {
840 req.serverError.opcode = htons(5);
841 req.serverError.errorcode = htons(1);
842 strcpy(req.serverError.errormessage, "File not found or No Access");
843 logMess(&req, 1);
844 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
845 req.attempt = UCHAR_MAX;
846 continue;
847 }
848 }
849 else
850 {
851 if (!cfig.fileWrite && !cfig.fileOverwrite)
852 {
853 req.serverError.opcode = htons(5);
854 req.serverError.errorcode = htons(2);
855 strcpy(req.serverError.errormessage, "PUT Access Denied");
856 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
857 logMess(&req, 1);
858 req.attempt = UCHAR_MAX;
859 continue;
860 }
861
862 req.file = fopen(req.path, "rb");
863
864 if (req.file)
865 {
866 fclose(req.file);
867 req.file = NULL;
868
869 if (!cfig.fileOverwrite)
870 {
871 req.serverError.opcode = htons(5);
872 req.serverError.errorcode = htons(6);
873 strcpy(req.serverError.errormessage, "File already exists");
874 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
875 logMess(&req, 1);
876 req.attempt = UCHAR_MAX;
877 continue;
878 }
879 }
880 else if (!cfig.fileWrite)
881 {
882 req.serverError.opcode = htons(5);
883 req.serverError.errorcode = htons(2);
884 strcpy(req.serverError.errormessage, "Create File Access Denied");
885 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
886 logMess(&req, 1);
887 req.attempt = UCHAR_MAX;
888 continue;
889 }
890
891 errno = 0;
892
893 if (!strcasecmp(req.mode, "netascii") || !strcasecmp(req.mode, "ascii"))
894 req.file = fopen(req.path, "wt");
895 else
896 req.file = fopen(req.path, "wb");
897
898 if (errno || !req.file)
899 {
900 req.serverError.opcode = htons(5);
901 req.serverError.errorcode = htons(2);
902 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
903 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
904 logMess(&req, 1);
905 req.attempt = UCHAR_MAX;
906 continue;
907 }
908 }
909
910 setvbuf(req.file, NULL, _IOFBF, 5 * req.blksize);
911
912 if (*inPtr)
913 {
914 fetchAck = true;
915 char *outPtr = req.mesout.buffer;
916 req.mesout.opcode = htons(6);
917 MYDWORD val;
918 while (*inPtr)
919 {
920 //printf("%s\n", inPtr);
921 if (!strcasecmp(inPtr, "blksize"))
922 {
923 strcpy(outPtr, inPtr);
924 outPtr += strlen(outPtr) + 1;
925 inPtr += strlen(inPtr) + 1;
926 val = atol(inPtr);
927
928 if (val < 512)
929 val = 512;
930 else if (val > blksize)
931 val = blksize;
932
933 req.blksize = val;
934 sprintf(outPtr, "%u", val);
935 outPtr += strlen(outPtr) + 1;
936 }
937 else if (!strcasecmp(inPtr, "tsize"))
938 {
939 strcpy(outPtr, inPtr);
940 outPtr += strlen(outPtr) + 1;
941 inPtr += strlen(inPtr) + 1;
942
943 if (ntohs(req.mesin.opcode) == 1)
944 {
945 if (!fseek(req.file, 0, SEEK_END))
946 {
947 if (ftell(req.file) >= 0)
948 {
949 req.tsize = ftell(req.file);
950 sprintf(outPtr, "%u", req.tsize);
951 outPtr += strlen(outPtr) + 1;
952 }
953 else
954 {
955 req.serverError.opcode = htons(5);
956 req.serverError.errorcode = htons(2);
957 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
958 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
959 logMess(&req, 1);
960 req.attempt = UCHAR_MAX;
961 break;
962 }
963 }
964 else
965 {
966 req.serverError.opcode = htons(5);
967 req.serverError.errorcode = htons(2);
968 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
969 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
970 logMess(&req, 1);
971 req.attempt = UCHAR_MAX;
972 break;
973 }
974 }
975 else
976 {
977 req.tsize = 0;
978 sprintf(outPtr, "%u", req.tsize);
979 outPtr += strlen(outPtr) + 1;
980 }
981 }
982 else if (!strcasecmp(inPtr, "timeout"))
983 {
984 strcpy(outPtr, inPtr);
985 outPtr += strlen(outPtr) + 1;
986 inPtr += strlen(inPtr) + 1;
987 val = atoi(inPtr);
988
989 if (val < 1)
990 val = 1;
991 else if (val > UCHAR_MAX)
992 val = UCHAR_MAX;
993
994 req.timeout = val;
995 req.expiry = time(NULL) + req.timeout;
996 sprintf(outPtr, "%u", val);
997 outPtr += strlen(outPtr) + 1;
998 }
999
1000 inPtr += strlen(inPtr) + 1;
1001 //printf("=%u\n", val);
1002 }
1003
1004 if (req.attempt >= 3)
1005 continue;
1006
1007 errno = 0;
1008 req.bytesReady = (MYDWORD)outPtr - (MYDWORD)&req.mesout;
1009 //printf("Bytes Ready=%u\n", req.bytesReady);
1010 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1011 errno = WSAGetLastError();
1012 }
1013 else if (htons(req.mesin.opcode) == 2)
1014 {
1015 req.acout.opcode = htons(4);
1016 req.acout.block = htons(0);
1017 errno = 0;
1018 req.bytesReady = 4;
1019 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1020 errno = WSAGetLastError();
1021 }
1022
1023 if (errno)
1024 {
1025 sprintf(req.serverError.errormessage, "Communication Error");
1026 logMess(&req, 1);
1027 req.attempt = UCHAR_MAX;
1028 continue;
1029 }
1030 else if (ntohs(req.mesin.opcode) == 1)
1031 {
1032 errno = 0;
1033 req.pkt[0] = (packet*)calloc(1, req.blksize + 4);
1034 req.pkt[1] = (packet*)calloc(1, req.blksize + 4);
1035
1036 if (errno || !req.pkt[0] || !req.pkt[1])
1037 {
1038 sprintf(req.serverError.errormessage, "Memory Error");
1039 logMess(&req, 1);
1040 req.attempt = UCHAR_MAX;
1041 continue;
1042 }
1043
1044 long ftellLoc = ftell(req.file);
1045
1046 if (ftellLoc > 0)
1047 {
1048 if (fseek(req.file, 0, SEEK_SET))
1049 {
1050 req.serverError.opcode = htons(5);
1051 req.serverError.errorcode = htons(2);
1052 strcpy(req.serverError.errormessage, "File Access Error");
1053 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1054 logMess(&req, 1);
1055 req.attempt = UCHAR_MAX;
1056 continue;
1057 }
1058 }
1059 else if (ftellLoc < 0)
1060 {
1061 req.serverError.opcode = htons(5);
1062 req.serverError.errorcode = htons(2);
1063 strcpy(req.serverError.errormessage, "File Access Error");
1064 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1065 logMess(&req, 1);
1066 req.attempt = UCHAR_MAX;
1067 continue;
1068 }
1069
1070 errno = 0;
1071 req.pkt[0]->opcode = htons(3);
1072 req.pkt[0]->block = htons(1);
1073 req.bytesRead[0] = fread(&req.pkt[0]->buffer, 1, req.blksize, req.file);
1074
1075 if (errno)
1076 {
1077 req.serverError.opcode = htons(5);
1078 req.serverError.errorcode = htons(2);
1079 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
1080 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1081 logMess(&req, 1);
1082 req.attempt = UCHAR_MAX;
1083 continue;
1084 }
1085
1086 if (req.bytesRead[0] == req.blksize)
1087 {
1088 req.pkt[1]->opcode = htons(3);
1089 req.pkt[1]->block = htons(2);
1090 req.bytesRead[1] = fread(&req.pkt[1]->buffer, 1, req.blksize, req.file);
1091 if (req.bytesRead[1] < req.blksize)
1092 {
1093 fclose(req.file);
1094 req.file = 0;
1095 }
1096 }
1097 else
1098 {
1099 fclose(req.file);
1100 req.file = 0;
1101 }
1102
1103 if (errno)
1104 {
1105 req.serverError.opcode = htons(5);
1106 req.serverError.errorcode = htons(2);
1107 strcpy(req.serverError.errormessage, "Invalid Path or No Access");
1108 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1109 logMess(&req, 1);
1110 req.attempt = UCHAR_MAX;
1111 continue;
1112 }
1113
1114 while (req.attempt <= 3)
1115 {
1116 if (fetchAck)
1117 {
1118 FD_ZERO(&req.readfds);
1119 req.tv.tv_sec = 1;
1120 req.tv.tv_usec = 0;
1121 FD_SET(req.sock, &req.readfds);
1122 select(req.sock + 1, &req.readfds, NULL, NULL, &req.tv);
1123
1124 if (FD_ISSET(req.sock, &req.readfds))
1125 {
1126 errno = 0;
1127 req.bytesRecd = recv(req.sock, (char*)&req.mesin, sizeof(message), 0);
1128 errno = WSAGetLastError();
1129 if (req.bytesRecd <= 0 || errno)
1130 {
1131 sprintf(req.serverError.errormessage, "Communication Error");
1132 logMess(&req, 1);
1133 req.attempt = UCHAR_MAX;
1134 break;
1135 }
1136 else if(req.bytesRecd >= 4 && ntohs(req.mesin.opcode) == 4)
1137 {
1138 if (ntohs(req.acin.block) == req.block)
1139 {
1140 req.block++;
1141 req.fblock++;
1142 req.attempt = 0;
1143 }
1144 else if (req.expiry > time(NULL))
1145 continue;
1146 else
1147 req.attempt++;
1148 }
1149 else if (ntohs(req.mesin.opcode) == 5)
1150 {
1151 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);
1152 logMess(&req, 1);
1153 req.attempt = UCHAR_MAX;
1154 break;
1155 }
1156 else
1157 {
1158 req.serverError.opcode = htons(5);
1159 req.serverError.errorcode = htons(4);
1160 sprintf(req.serverError.errormessage, "Unexpected Option Code %i", ntohs(req.mesin.opcode));
1161 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1162 logMess(&req, 1);
1163 req.attempt = UCHAR_MAX;
1164 break;
1165 }
1166 }
1167 else if (req.expiry > time(NULL))
1168 continue;
1169 else
1170 req.attempt++;
1171 }
1172 else
1173 {
1174 fetchAck = true;
1175 req.acin.block = 1;
1176 req.block = 1;
1177 req.fblock = 1;
1178 }
1179
1180 if (req.attempt >= 3)
1181 {
1182 req.serverError.opcode = htons(5);
1183 req.serverError.errorcode = htons(0);
1184
1185 if (req.fblock && !req.block)
1186 strcpy(req.serverError.errormessage, "Large File, Block# Rollover not supported by Client");
1187 else
1188 strcpy(req.serverError.errormessage, "Timeout");
1189
1190 logMess(&req, 1);
1191 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1192 req.attempt = UCHAR_MAX;
1193 break;
1194 }
1195 else if (!req.fblock)
1196 {
1197 errno = 0;
1198 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1199 errno = WSAGetLastError();
1200 if (errno)
1201 {
1202 sprintf(req.serverError.errormessage, "Communication Error");
1203 logMess(&req, 1);
1204 req.attempt = UCHAR_MAX;
1205 break;
1206 }
1207 req.expiry = time(NULL) + req.timeout;
1208 }
1209 else if (ntohs(req.pkt[0]->block) == req.block)
1210 {
1211 errno = 0;
1212 send(req.sock, (const char*)req.pkt[0], req.bytesRead[0] + 4, 0);
1213 errno = WSAGetLastError();
1214 if (errno)
1215 {
1216 sprintf(req.serverError.errormessage, "Communication Error");
1217 logMess(&req, 1);
1218 req.attempt = UCHAR_MAX;
1219 break;
1220 }
1221 req.expiry = time(NULL) + req.timeout;
1222
1223 if (req.file)
1224 {
1225 req.tblock = ntohs(req.pkt[1]->block) + 1;
1226 if (req.tblock == req.block)
1227 {
1228 req.pkt[1]->block = htons(++req.tblock);
1229 req.bytesRead[1] = fread(&req.pkt[1]->buffer, 1, req.blksize, req.file);
1230
1231 if (errno)
1232 {
1233 req.serverError.opcode = htons(5);
1234 req.serverError.errorcode = htons(4);
1235 sprintf(req.serverError.errormessage, strerror(errno));
1236 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1237 logMess(&req, 1);
1238 req.attempt = UCHAR_MAX;
1239 break;
1240 }
1241 else if (req.bytesRead[1] < req.blksize)
1242 {
1243 fclose(req.file);
1244 req.file = 0;
1245 }
1246 }
1247 }
1248 }
1249 else if (ntohs(req.pkt[1]->block) == req.block)
1250 {
1251 errno = 0;
1252 send(req.sock, (const char*)req.pkt[1], req.bytesRead[1] + 4, 0);
1253 errno = WSAGetLastError();
1254 if (errno)
1255 {
1256 sprintf(req.serverError.errormessage, "Communication Error");
1257 logMess(&req, 1);
1258 req.attempt = UCHAR_MAX;
1259 break;
1260 }
1261
1262 req.expiry = time(NULL) + req.timeout;
1263
1264 if (req.file)
1265 {
1266 req.tblock = ntohs(req.pkt[0]->block) + 1;
1267 if (req.tblock == req.block)
1268 {
1269 req.pkt[0]->block = htons(++req.tblock);
1270 req.bytesRead[0] = fread(&req.pkt[0]->buffer, 1, req.blksize, req.file);
1271 if (errno)
1272 {
1273 req.serverError.opcode = htons(5);
1274 req.serverError.errorcode = htons(4);
1275 sprintf(req.serverError.errormessage, strerror(errno));
1276 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1277 logMess(&req, 1);
1278 req.attempt = UCHAR_MAX;
1279 break;
1280 }
1281 else if (req.bytesRead[0] < req.blksize)
1282 {
1283 fclose(req.file);
1284 req.file = 0;
1285 }
1286 }
1287 }
1288 }
1289 else
1290 {
1291 sprintf(req.serverError.errormessage, "%u Blocks Served", req.fblock - 1);
1292 logMess(&req, 2);
1293 req.attempt = UCHAR_MAX;
1294 break;
1295 }
1296 }
1297 }
1298 else if (ntohs(req.mesin.opcode) == 2)
1299 {
1300 errno = 0;
1301 req.pkt[0] = (packet*)calloc(1, req.blksize + 4);
1302
1303 if (errno || !req.pkt[0])
1304 {
1305 sprintf(req.serverError.errormessage, "Memory Error");
1306 logMess(&req, 1);
1307 req.attempt = UCHAR_MAX;
1308 continue;
1309 }
1310
1311 while (req.attempt <= 3)
1312 {
1313 FD_ZERO(&req.readfds);
1314 req.tv.tv_sec = 1;
1315 req.tv.tv_usec = 0;
1316 FD_SET(req.sock, &req.readfds);
1317 select(req.sock + 1, &req.readfds, NULL, NULL, &req.tv);
1318
1319 if (FD_ISSET(req.sock, &req.readfds))
1320 {
1321 errno = 0;
1322 req.bytesRecd = recv(req.sock, (char*)req.pkt[0], req.blksize + 4, 0);
1323 errno = WSAGetLastError();
1324
1325 if (errno)
1326 {
1327 sprintf(req.serverError.errormessage, "Communication Error");
1328 logMess(&req, 1);
1329 req.attempt = UCHAR_MAX;
1330 break;
1331 }
1332 }
1333 else
1334 req.bytesRecd = 0;
1335
1336 if (req.bytesRecd >= 4)
1337 {
1338 if (ntohs(req.pkt[0]->opcode) == 3)
1339 {
1340 req.tblock = req.block + 1;
1341
1342 if (ntohs(req.pkt[0]->block) == req.tblock)
1343 {
1344 req.acout.opcode = htons(4);
1345 req.acout.block = req.pkt[0]->block;
1346 req.block++;
1347 req.fblock++;
1348 req.bytesReady = 4;
1349 req.expiry = time(NULL) + req.timeout;
1350
1351 errno = 0;
1352 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1353 errno = WSAGetLastError();
1354
1355 if (errno)
1356 {
1357 sprintf(req.serverError.errormessage, "Communication Error");
1358 logMess(&req, 1);
1359 req.attempt = UCHAR_MAX;
1360 break;
1361 }
1362
1363 if (req.bytesRecd > 4)
1364 {
1365 errno = 0;
1366 if (fwrite(&req.pkt[0]->buffer, req.bytesRecd - 4, 1, req.file) != 1 || errno)
1367 {
1368 req.serverError.opcode = htons(5);
1369 req.serverError.errorcode = htons(3);
1370 strcpy(req.serverError.errormessage, "Disk full or allocation exceeded");
1371 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1372 logMess(&req, 1);
1373 req.attempt = UCHAR_MAX;
1374 break;
1375 }
1376 else
1377 req.attempt = 0;
1378 }
1379 else
1380 req.attempt = 0;
1381
1382 if ((MYWORD)req.bytesRecd < req.blksize + 4)
1383 {
1384 fclose(req.file);
1385 req.file = 0;
1386 sprintf(req.serverError.errormessage, "%u Blocks Received", req.fblock);
1387 logMess(&req, 2);
1388 req.attempt = UCHAR_MAX;
1389 break;
1390 }
1391 }
1392 else if (req.expiry > time(NULL))
1393 continue;
1394 else if (req.attempt >= 3)
1395 {
1396 req.serverError.opcode = htons(5);
1397 req.serverError.errorcode = htons(0);
1398
1399 if (req.fblock && !req.block)
1400 strcpy(req.serverError.errormessage, "Large File, Block# Rollover not supported by Client");
1401 else
1402 strcpy(req.serverError.errormessage, "Timeout");
1403
1404 logMess(&req, 1);
1405 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1406 req.attempt = UCHAR_MAX;
1407 break;
1408 }
1409 else
1410 {
1411 req.expiry = time(NULL) + req.timeout;
1412 errno = 0;
1413 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1414 errno = WSAGetLastError();
1415 req.attempt++;
1416
1417 if (errno)
1418 {
1419 sprintf(req.serverError.errormessage, "Communication Error");
1420 logMess(&req, 1);
1421 req.attempt = UCHAR_MAX;
1422 break;
1423 }
1424 }
1425 }
1426 else if (req.bytesRecd > (int)sizeof(message))
1427 {
1428 req.serverError.opcode = htons(5);
1429 req.serverError.errorcode = htons(4);
1430 sprintf(req.serverError.errormessage, "Error: Incoming Packet too large");
1431 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1432 logMess(&req, 1);
1433 req.attempt = UCHAR_MAX;
1434 break;
1435 }
1436 else if (ntohs(req.pkt[0]->opcode) == 5)
1437 {
1438 sprintf(req.serverError.errormessage, "Error Code %i at Client, %s", ntohs(req.pkt[0]->block), &req.pkt[0]->buffer);
1439 logMess(&req, 1);
1440 req.attempt = UCHAR_MAX;
1441 break;
1442 }
1443 else
1444 {
1445 req.serverError.opcode = htons(5);
1446 req.serverError.errorcode = htons(4);
1447 sprintf(req.serverError.errormessage, "Unexpected Option Code %i", ntohs(req.pkt[0]->opcode));
1448 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1449 logMess(&req, 1);
1450 req.attempt = UCHAR_MAX;
1451 break;
1452 }
1453 }
1454 else if (req.expiry > time(NULL))
1455 continue;
1456 else if (req.attempt >= 3)
1457 {
1458 req.serverError.opcode = htons(5);
1459 req.serverError.errorcode = htons(0);
1460
1461 if (req.fblock && !req.block)
1462 strcpy(req.serverError.errormessage, "Large File, Block# Rollover not supported by Client");
1463 else
1464 strcpy(req.serverError.errormessage, "Timeout");
1465
1466 logMess(&req, 1);
1467 send(req.sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0);
1468 req.attempt = UCHAR_MAX;
1469 break;
1470 }
1471 else
1472 {
1473 req.expiry = time(NULL) + req.timeout;
1474 errno = 0;
1475 send(req.sock, (const char*)&req.mesout, req.bytesReady, 0);
1476 errno = WSAGetLastError();
1477 req.attempt++;
1478
1479 if (errno)
1480 {
1481 sprintf(req.serverError.errormessage, "Communication Error");
1482 logMess(&req, 1);
1483 req.attempt = UCHAR_MAX;
1484 break;
1485 }
1486 }
1487 }
1488 }
1489 }
1490 while (cleanReq(&req));
1491
1492 WaitForSingleObject(cEvent, INFINITE);
1493 totalThreads--;
1494 SetEvent(cEvent);
1495
1496 //printf("Thread %u Killed\n",GetCurrentThreadId());
1497 _endthread();
1498 return;
1499 }
1500
1501 bool cleanReq(request* req)
1502 {
1503 //printf("cleaning\n");
1504
1505 if (req->file)
1506 fclose(req->file);
1507
1508 if (!(req->sock == INVALID_SOCKET))
1509 {
1510 //printf("Here\n");
1511 closesocket(req->sock);
1512 }
1513
1514 if (req->pkt[0])
1515 free(req->pkt[0]);
1516
1517 if (req->pkt[1])
1518 free(req->pkt[1]);
1519
1520 WaitForSingleObject(cEvent, INFINITE);
1521 activeThreads--;
1522 SetEvent(cEvent);
1523
1524 //printf("cleaned\n");
1525
1526 return (totalThreads <= minThreads);
1527 }
1528
1529 bool getSection(const char *sectionName, char *buffer, MYBYTE serial, char *fileName)
1530 {
1531 //printf("%s=%s\n",fileName,sectionName);
1532 char section[128];
1533 sprintf(section, "[%s]", sectionName);
1534 myUpper(section);
1535 FILE *f = fopen(fileName, "rt");
1536 char buff[512];
1537 MYBYTE found = 0;
1538
1539 if (f)
1540 {
1541 while (fgets(buff, 511, f))
1542 {
1543 myUpper(buff);
1544 myTrim(buff, buff);
1545
1546 if (strstr(buff, section) == buff)
1547 {
1548 found++;
1549 if (found == serial)
1550 {
1551 //printf("%s=%s\n",fileName,sectionName);
1552 while (fgets(buff, 511, f))
1553 {
1554 myTrim(buff, buff);
1555
1556 if (strstr(buff, "[") == buff)
1557 break;
1558
1559 if (((*buff) >= '0' && (*buff) <= '9') || ((*buff) >= 'A' && (*buff) <= 'Z') || ((*buff) >= 'a' && (*buff) <= 'z') || ((*buff) && strchr("/\\?*", (*buff))))
1560 {
1561 buffer += sprintf(buffer, "%s", buff);
1562 buffer++;
1563 }
1564 }
1565 break;
1566 }
1567 }
1568 }
1569 fclose(f);
1570 }
1571
1572 *buffer = 0;
1573 *(buffer + 1) = 0;
1574 return (found == serial);
1575 }
1576
1577 FILE *openSection(const char *sectionName, MYBYTE serial, char *fileName)
1578 {
1579 //printf("%s=%s\n",fileName,sectionName);
1580 char section[128];
1581 sprintf(section, "[%s]", sectionName);
1582 myUpper(section);
1583 FILE *f = fopen(fileName, "rt");
1584 char buff[512];
1585 MYBYTE found = 0;
1586
1587 if (f)
1588 {
1589 while (fgets(buff, 511, f))
1590 {
1591 myUpper(buff);
1592 myTrim(buff, buff);
1593
1594 if (strstr(buff, section) == buff)
1595 {
1596 found++;
1597
1598 if (found == serial)
1599 return f;
1600 }
1601 }
1602 fclose(f);
1603 }
1604 return NULL;
1605 }
1606
1607 char *readSection(char* buff, FILE *f)
1608 {
1609 while (fgets(buff, 511, f))
1610 {
1611 myTrim(buff, buff);
1612
1613 if (*buff == '[')
1614 break;
1615
1616 if (((*buff) >= '0' && (*buff) <= '9') || ((*buff) >= 'A' && (*buff) <= 'Z') || ((*buff) >= 'a' && (*buff) <= 'z') || ((*buff) && strchr("/\\?*", (*buff))))
1617 return buff;
1618 }
1619
1620 fclose(f);
1621 return NULL;
1622 }
1623
1624 char* myGetToken(char* buff, MYBYTE index)
1625 {
1626 while (*buff)
1627 {
1628 if (index)
1629 index--;
1630 else
1631 break;
1632
1633 buff += strlen(buff) + 1;
1634 }
1635
1636 return buff;
1637 }
1638
1639 MYWORD myTokenize(char *target, char *source, char *sep, bool whiteSep)
1640 {
1641 bool found = true;
1642 char *dp = target;
1643 MYWORD kount = 0;
1644
1645 while (*source)
1646 {
1647 if (sep && sep[0] && strchr(sep, (*source)))
1648 {
1649 found = true;
1650 source++;
1651 continue;
1652 }
1653 else if (whiteSep && (*source) <= 32)
1654 {
1655 found = true;
1656 source++;
1657 continue;
1658 }
1659
1660 if (found)
1661 {
1662 if (target != dp)
1663 {
1664 *dp = 0;
1665 dp++;
1666 }
1667 kount++;
1668 }
1669
1670 found = false;
1671 *dp = *source;
1672 dp++;
1673 source++;
1674 }
1675
1676 *dp = 0;
1677 dp++;
1678 *dp = 0;
1679
1680 //printf("%s\n", target);
1681
1682 return kount;
1683 }
1684
1685 char* myTrim(char *target, char *source)
1686 {
1687 while ((*source) && (*source) <= 32)
1688 source++;
1689
1690 int i = 0;
1691
1692 for (; i < 511 && source[i]; i++)
1693 target[i] = source[i];
1694
1695 target[i] = source[i];
1696 i--;
1697
1698 for (; i >= 0 && target[i] <= 32; i--)
1699 target[i] = 0;
1700
1701 return target;
1702 }
1703
1704 /*
1705 void mySplit(char *name, char *value, char *source, char splitChar)
1706 {
1707 char *dp = strchr(source, splitChar);
1708
1709 if (dp)
1710 {
1711 strncpy(name, source, (dp - source));
1712 name[dp - source] = 0;
1713 strcpy(value, dp + 1);
1714 myTrim(name, name);
1715 myTrim(value, value);
1716 }
1717 else
1718 {
1719 strcpy(name, source);
1720 myTrim(name, name);
1721 *value = 0;
1722 }
1723 }
1724 */
1725
1726 void mySplit(char *name, char *value, char *source, char splitChar)
1727 {
1728 int i = 0;
1729 int j = 0;
1730 int k = 0;
1731
1732 for (; source[i] && j <= 510 && source[i] != splitChar; i++, j++)
1733 {
1734 name[j] = source[i];
1735 }
1736
1737 if (source[i])
1738 {
1739 i++;
1740 for (; k <= 510 && source[i]; i++, k++)
1741 {
1742 value[k] = source[i];
1743 }
1744 }
1745
1746 name[j] = 0;
1747 value[k] = 0;
1748
1749 myTrim(name, name);
1750 myTrim(value, value);
1751 //printf("%s %s\n", name, value);
1752 }
1753
1754
1755 char *IP2String(char *target, MYDWORD ip)
1756 {
1757 data15 inaddr;
1758 inaddr.ip = ip;
1759 sprintf(target, "%u.%u.%u.%u", inaddr.octate[0], inaddr.octate[1], inaddr.octate[2], inaddr.octate[3]);
1760 return target;
1761 }
1762
1763 bool isIP(char *string)
1764 {
1765 int j = 0;
1766
1767 for (; *string; string++)
1768 {
1769 if (*string == '.' && *(string + 1) != '.')
1770 j++;
1771 else if (*string < '0' || *string > '9')
1772 return 0;
1773 }
1774
1775 if (j == 3)
1776 return 1;
1777 else
1778 return 0;
1779 }
1780
1781 char *myUpper(char *string)
1782 {
1783 char diff = 'a' - 'A';
1784 MYWORD len = strlen(string);
1785 for (int i = 0; i < len; i++)
1786 if (string[i] >= 'a' && string[i] <= 'z')
1787 string[i] -= diff;
1788 return string;
1789 }
1790
1791 char *myLower(char *string)
1792 {
1793 char diff = 'a' - 'A';
1794 MYWORD len = strlen(string);
1795 for (int i = 0; i < len; i++)
1796 if (string[i] >= 'A' && string[i] <= 'Z')
1797 string[i] += diff;
1798 return string;
1799 }
1800
1801 void init(void *lpParam)
1802 {
1803 memset(&cfig, 0, sizeof(cfig));
1804
1805 GetModuleFileName(NULL, extbuff, _MAX_PATH);
1806 char *fileExt = strrchr(extbuff, '.');
1807 *fileExt = 0;
1808 sprintf(iniFile, "%s.ini", extbuff);
1809 sprintf(lnkFile, "%s.url", extbuff);
1810 fileExt = strrchr(extbuff, '\\');
1811 *fileExt = 0;
1812 fileExt++;
1813 sprintf(logFile, "%s\\log\\%s%%Y%%m%%d.log", extbuff, fileExt);
1814
1815 FILE *f = NULL;
1816 char raw[512];
1817 char name[512];
1818 char value[512];
1819
1820 if (verbatim)
1821 {
1822 cfig.logLevel = 2;
1823 printf("%s\n\n", sVersion);
1824 }
1825 else if ((f = openSection("LOGGING", 1, iniFile)))
1826 {
1827 cfig.logLevel = 1;
1828 tempbuff[0] = 0;
1829
1830 while (readSection(raw, f))
1831 {
1832 if (!strcasecmp(raw, "None"))
1833 cfig.logLevel = 0;
1834 else if (!strcasecmp(raw, "Errors"))
1835 cfig.logLevel = 1;
1836 else if (!strcasecmp(raw, "All"))
1837 cfig.logLevel = 2;
1838 else
1839 sprintf(tempbuff, "Section [LOGGING], Invalid LogLevel: %s", raw);
1840 }
1841 }
1842
1843 if (!verbatim && cfig.logLevel && logFile[0])
1844 {
1845 time_t t = time(NULL);
1846 tm *ttm = localtime(&t);
1847 loggingDay = ttm->tm_yday;
1848 strftime(extbuff, sizeof(extbuff), logFile, ttm);
1849
1850 cfig.logfile = fopen(extbuff, "at");
1851
1852 if (cfig.logfile)
1853 {
1854 WritePrivateProfileString("InternetShortcut","URL", extbuff, lnkFile);
1855 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile);
1856 WritePrivateProfileString("InternetShortcut","IconFile", extbuff, lnkFile);
1857 sprintf(logBuff, "%s Starting..", sVersion);
1858 logMess(logBuff, 1);
1859
1860 if (tempbuff[0])
1861 logMess(tempbuff, 0);
1862 }
1863 }
1864
1865 MYWORD wVersionRequested = MAKEWORD(1, 1);
1866 WSAStartup(wVersionRequested, &cfig.wsaData);
1867
1868 if (cfig.wsaData.wVersion != wVersionRequested)
1869 {
1870 sprintf(logBuff, "WSAStartup Error");
1871 logMess(logBuff, 1);
1872 }
1873
1874 if ((f = openSection("HOME", 1, iniFile)))
1875 {
1876 while (readSection(raw, f))
1877 {
1878 mySplit(name, value, raw, '=');
1879
1880 if (strlen(value))
1881 {
1882 if (!cfig.homes[0].alias[0] && cfig.homes[0].target[0])
1883 {
1884 sprintf(logBuff, "Section [HOME], alias and bare path mixup, entry %s ignored", raw);
1885 logMess(logBuff, 1);
1886 }
1887 else if (strchr(name, notFileSep) || strchr(name, fileSep) || strchr(name, '>') || strchr(name, '<') || strchr(name, '.'))
1888 {
1889 sprintf(logBuff, "Section [HOME], invalid chars in alias %s, entry ignored", name);
1890 logMess(logBuff, 1);
1891 }
1892 else if (name[0] && strlen(name) < 64 && value[0])
1893 {
1894 for (int i = 0; i < 8; i++)
1895 {
1896 if (cfig.homes[i].alias[0] && !strcasecmp(name, cfig.homes[i].alias))
1897 {
1898 sprintf(logBuff, "Section [HOME], Duplicate Entry: %s ignored", raw);
1899 logMess(logBuff, 1);
1900 break;
1901 }
1902 else if (!cfig.homes[i].alias[0])
1903 {
1904 strcpy(cfig.homes[i].alias, name);
1905 strcpy(cfig.homes[i].target, value);
1906
1907 if (cfig.homes[i].target[strlen(cfig.homes[i].target) - 1] != fileSep)
1908 {
1909 tempbuff[0] = fileSep;
1910 tempbuff[1] = 0;
1911 strcat(cfig.homes[i].target, tempbuff);
1912 }
1913
1914 break;
1915 }
1916 }
1917 }
1918 else
1919 {
1920 sprintf(logBuff, "Section [HOME], alias %s too large", name);
1921 logMess(logBuff, 1);
1922 }
1923 }
1924 else if (!cfig.homes[0].alias[0] && !cfig.homes[0].target[0])
1925 {
1926 strcpy(cfig.homes[0].target, name);
1927
1928 if (cfig.homes[0].target[strlen(cfig.homes[0].target) - 1] != fileSep)
1929 {
1930 tempbuff[0] = fileSep;
1931 tempbuff[1] = 0;
1932 strcat(cfig.homes[0].target, tempbuff);
1933 }
1934 }
1935 else if (cfig.homes[0].alias[0])
1936 {
1937 sprintf(logBuff, "Section [HOME], alias and bare path mixup, entry %s ignored", raw);
1938 logMess(logBuff, 1);
1939 }
1940 else if (cfig.homes[0].target[0])
1941 {
1942 sprintf(logBuff, "Section [HOME], Duplicate Path: %s ignored", raw);
1943 logMess(logBuff, 1);
1944 }
1945 else
1946 {
1947 sprintf(logBuff, "Section [HOME], missing = sign, Invalid Entry: %s ignored", raw);
1948 logMess(logBuff, 1);
1949 }
1950 }
1951 }
1952
1953 if (!cfig.homes[0].target[0])
1954 {
1955 GetModuleFileName(NULL, cfig.homes[0].target, UCHAR_MAX);
1956 char *iniFileExt = strrchr(cfig.homes[0].target, fileSep);
1957 *(++iniFileExt) = 0;
1958 }
1959
1960 cfig.fileRead = true;
1961
1962 if ((f = openSection("TFTP-OPTIONS", 1, iniFile)))
1963 {
1964 while (readSection(raw, f))
1965 {
1966 mySplit(name, value, raw, '=');
1967
1968 if (strlen(value))
1969 {
1970 if (!strcasecmp(name, "blksize"))
1971 {
1972 MYDWORD tblksize = atol(value);
1973
1974 if (tblksize < 512)
1975 blksize = 512;
1976 else if (tblksize > USHRT_MAX - 32)
1977 blksize = USHRT_MAX - 32;
1978 else
1979 blksize = tblksize;
1980 }
1981 else if (!strcasecmp(name, "threadpoolsize"))
1982 {
1983 minThreads = atol(value);
1984 if (minThreads < 1)
1985 minThreads = 0;
1986 else if (minThreads > 100)
1987 minThreads = 100;
1988 }
1989 else if (!strcasecmp(name, "timeout"))
1990 {
1991 timeout = atol(value);
1992 if (timeout < 1)
1993 timeout = 1;
1994 else if (timeout > UCHAR_MAX)
1995 timeout = UCHAR_MAX;
1996 }
1997 else if (!strcasecmp(name, "Read"))
1998 {
1999 if (strchr("Yy", *value))
2000 cfig.fileRead = true;
2001 else
2002 cfig.fileRead = false;
2003 }
2004 else if (!strcasecmp(name, "Write"))
2005 {
2006 if (strchr("Yy", *value))
2007 cfig.fileWrite = true;
2008 else
2009 cfig.fileWrite = false;
2010 }
2011 else if (!strcasecmp(name, "Overwrite"))
2012 {
2013 if (strchr("Yy", *value))
2014 cfig.fileOverwrite = true;
2015 else
2016 cfig.fileOverwrite = false;
2017 }
2018 else if (!strcasecmp(name, "port-range"))
2019 {
2020 char *ptr = strchr(value, '-');
2021 if (ptr)
2022 {
2023 *ptr = 0;
2024 cfig.minport = atol(value);
2025 cfig.maxport = atol(++ptr);
2026
2027 if (cfig.minport < 1024 || cfig.minport >= USHRT_MAX || cfig.maxport < 1024 || cfig.maxport >= USHRT_MAX || cfig.minport > cfig.maxport)
2028 {
2029 cfig.minport = 0;
2030 cfig.maxport = 0;
2031
2032 sprintf(logBuff, "Invalid port range %s", value);
2033 logMess(logBuff, 1);
2034 }
2035 }
2036 else
2037 {
2038 sprintf(logBuff, "Invalid port range %s", value);
2039 logMess(logBuff, 1);
2040 }
2041 }
2042 else
2043 {
2044 sprintf(logBuff, "Warning: unknown option %s, ignored", name);
2045 logMess(logBuff, 1);
2046 }
2047 }
2048 }
2049 }
2050
2051 if ((f = openSection("ALLOWED-CLIENTS", 1, iniFile)))
2052 {
2053 int i = 0;
2054
2055 while (readSection(raw, f))
2056 {
2057 #ifdef __REACTOS__
2058 if (i < _countof(cfig.hostRanges))
2059 #else
2060 if (i < 32)
2061 #endif
2062 {
2063 MYDWORD rs = 0;
2064 MYDWORD re = 0;
2065 mySplit(name, value, raw, '-');
2066 rs = htonl(my_inet_addr(name));
2067
2068 if (strlen(value))
2069 re = htonl(my_inet_addr(value));
2070 else
2071 re = rs;
2072
2073 if (rs && rs != INADDR_NONE && re && re != INADDR_NONE && rs <= re)
2074 {
2075 cfig.hostRanges[i].rangeStart = rs;
2076 cfig.hostRanges[i].rangeEnd = re;
2077 i++;
2078 }
2079 else
2080 {
2081 sprintf(logBuff, "Section [ALLOWED-CLIENTS] Invalid entry %s in ini file, ignored", raw);
2082 logMess(logBuff, 1);
2083 }
2084 }
2085 }
2086 }
2087
2088 if (verbatim)
2089 {
2090 printf("starting TFTP...\n");
2091 }
2092 else
2093 {
2094 sprintf(logBuff, "starting TFTP service");
2095 logMess(logBuff, 1);
2096 }
2097
2098 for (int i = 0; i < MAX_SERVERS; i++)
2099 if (cfig.homes[i].target[0])
2100 {
2101 sprintf(logBuff, "alias /%s is mapped to %s", cfig.homes[i].alias, cfig.homes[i].target);
2102 logMess(logBuff, 1);
2103 }
2104
2105 if (cfig.hostRanges[0].rangeStart)
2106 {
2107 char temp[128];
2108
2109 #ifdef __REACTOS__
2110 for (int i = 0; i < _countof(cfig.hostRanges) && cfig.hostRanges[i].rangeStart; i++)
2111 #else
2112 for (MYWORD i = 0; i <= sizeof(cfig.hostRanges) && cfig.hostRanges[i].rangeStart; i++)
2113 #endif
2114 {
2115 sprintf(logBuff, "%s", "permitted clients: ");
2116 sprintf(temp, "%s-", IP2String(tempbuff, htonl(cfig.hostRanges[i].rangeStart)));
2117 strcat(logBuff, temp);
2118 sprintf(temp, "%s", IP2String(tempbuff, htonl(cfig.hostRanges[i].rangeEnd)));
2119 strcat(logBuff, temp);
2120 logMess(logBuff, 1);
2121 }
2122 }
2123 else
2124 {
2125 sprintf(logBuff, "%s", "permitted clients: all");
2126 logMess(logBuff, 1);
2127 }
2128
2129 if (cfig.minport)
2130 {
2131 sprintf(logBuff, "server port range: %u-%u", cfig.minport, cfig.maxport);
2132 logMess(logBuff, 1);
2133 }
2134 else
2135 {
2136 sprintf(logBuff, "server port range: all");
2137 logMess(logBuff, 1);
2138 }
2139
2140 sprintf(logBuff, "max blksize: %u", blksize);
2141 logMess(logBuff, 1);
2142 sprintf(logBuff, "default blksize: %u", 512);
2143 logMess(logBuff, 1);
2144 sprintf(logBuff, "default timeout: %u", timeout);
2145 logMess(logBuff, 1);
2146 sprintf(logBuff, "file read allowed: %s", cfig.fileRead ? "Yes" : "No");
2147 logMess(logBuff, 1);
2148 sprintf(logBuff, "file create allowed: %s", cfig.fileWrite ? "Yes" : "No");
2149 logMess(logBuff, 1);
2150 sprintf(logBuff, "file overwrite allowed: %s", cfig.fileOverwrite ? "Yes" : "No");
2151 logMess(logBuff, 1);
2152
2153 if (!verbatim)
2154 {
2155 sprintf(logBuff, "logging: %s", cfig.logLevel > 1 ? "all" : "errors");
2156 logMess(logBuff, 1);
2157 }
2158
2159 lEvent = CreateEvent(
2160 NULL, // default security descriptor
2161 FALSE, // ManualReset
2162 TRUE, // Signalled
2163 TEXT("AchalTFTServerLogEvent")); // object name
2164
2165 if (lEvent == NULL)
2166 {
2167 printf("CreateEvent error: %lu\n", GetLastError());
2168 exit(-1);
2169 }
2170 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2171 {
2172 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2173 logMess(logBuff, 0);
2174 exit(-1);
2175 }
2176
2177 tEvent = CreateEvent(
2178 NULL, // default security descriptor
2179 FALSE, // ManualReset
2180 FALSE, // Signalled
2181 TEXT("AchalTFTServerThreadEvent")); // object name
2182
2183 if (tEvent == NULL)
2184 {
2185 printf("CreateEvent error: %lu\n", GetLastError());
2186 exit(-1);
2187 }
2188 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2189 {
2190 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2191 logMess(logBuff, 0);
2192 exit(-1);
2193 }
2194
2195 sEvent = CreateEvent(
2196 NULL, // default security descriptor
2197 FALSE, // ManualReset
2198 TRUE, // Signalled
2199 TEXT("AchalTFTServerSocketEvent")); // object name
2200
2201 if (sEvent == NULL)
2202 {
2203 printf("CreateEvent error: %lu\n", GetLastError());
2204 exit(-1);
2205 }
2206 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2207 {
2208 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2209 logMess(logBuff, 0);
2210 exit(-1);
2211 }
2212
2213 cEvent = CreateEvent(
2214 NULL, // default security descriptor
2215 FALSE, // ManualReset
2216 TRUE, // Signalled
2217 TEXT("AchalTFTServerCountEvent")); // object name
2218
2219 if (cEvent == NULL)
2220 {
2221 printf("CreateEvent error: %lu\n", GetLastError());
2222 exit(-1);
2223 }
2224 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
2225 {
2226 sprintf(logBuff, "CreateEvent opened an existing Event\nServer May already be Running");
2227 logMess(logBuff, 0);
2228 exit(-1);
2229 }
2230
2231 if (minThreads)
2232 {
2233 for (int i = 0; i < minThreads; i++)
2234 {
2235 _beginthread(
2236 processRequest, // thread function
2237 0, // default security attributes
2238 NULL); // argument to thread function
2239 }
2240
2241 sprintf(logBuff, "thread pool size: %u", minThreads);
2242 logMess(logBuff, 1);
2243 }
2244
2245 for (int i = 0; i < MAX_SERVERS && network.tftpConn[i].port; i++)
2246 {
2247 sprintf(logBuff, "listening on: %s:%i", IP2String(tempbuff, network.tftpConn[i].server), network.tftpConn[i].port);
2248 logMess(logBuff, 1);
2249 }
2250
2251 do
2252 {
2253 memset(&newNetwork, 0, sizeof(data1));
2254
2255 bool bindfailed = false;
2256
2257 if ((f = openSection("LISTEN-ON", 1, iniFile)))
2258 {
2259 MYBYTE i = 0;
2260
2261 while (readSection(raw, f))
2262 {
2263 MYWORD port = 69;
2264
2265 cfig.ifspecified = true;
2266 mySplit(name, value, raw, ':');
2267
2268 if (value[0])
2269 port = atoi(value);
2270
2271 if(i < MAX_SERVERS)
2272 {
2273 if (isIP(name))
2274 {
2275 MYDWORD addr = my_inet_addr(name);
2276
2277 if (!addr)
2278 {
2279 newNetwork.listenServers[0] = 0;
2280 newNetwork.listenPorts[0] = port;
2281 fclose(f);
2282 break;
2283 }
2284 else if (!findServer(newNetwork.listenServers, addr))
2285 {
2286 newNetwork.listenServers[i] = addr;
2287 newNetwork.listenPorts[i] = port;
2288 i++;
2289 }
2290 }
2291 else
2292 {
2293 sprintf(logBuff, "Warning: Section [LISTEN-ON], Invalid Interface Address %s, ignored", raw);
2294 logMess(logBuff, 1);
2295 }
2296 }
2297 }
2298 }
2299
2300 if (!cfig.ifspecified)
2301 {
2302 sprintf(logBuff, "detecting Interfaces..");
2303 logMess(logBuff, 1);
2304 getInterfaces(&newNetwork);
2305
2306 for (MYBYTE n = 0; n < MAX_SERVERS && newNetwork.staticServers[n]; n++)
2307 {
2308 newNetwork.listenServers[n] = newNetwork.staticServers[n];
2309 newNetwork.listenPorts[n] = 69;
2310 }
2311 }
2312
2313 MYBYTE i = 0;
2314
2315 for (int j = 0; j < MAX_SERVERS && newNetwork.listenPorts[j]; j++)
2316 {
2317 int k = 0;
2318
2319 for (; k < MAX_SERVERS && network.tftpConn[k].loaded; k++)
2320 {
2321 if (network.tftpConn[k].ready && network.tftpConn[k].server == newNetwork.listenServers[j] && network.tftpConn[k].port == newNetwork.listenPorts[j])
2322 break;
2323 }
2324
2325 if (network.tftpConn[k].ready && network.tftpConn[k].server == newNetwork.listenServers[j] && network.tftpConn[k].port == newNetwork.listenPorts[j])
2326 {
2327 memcpy(&(newNetwork.tftpConn[i]), &(network.tftpConn[k]), sizeof(tftpConnType));
2328
2329 if (newNetwork.maxFD < newNetwork.tftpConn[i].sock)
2330 newNetwork.maxFD = newNetwork.tftpConn[i].sock;
2331
2332 network.tftpConn[k].ready = false;
2333 //printf("%d, %s found\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2334 i++;
2335 continue;
2336 }
2337 else
2338 {
2339 newNetwork.tftpConn[i].sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
2340
2341 if (newNetwork.tftpConn[i].sock == INVALID_SOCKET)
2342 {
2343 bindfailed = true;
2344 sprintf(logBuff, "Failed to Create Socket");
2345 logMess(logBuff, 1);
2346 continue;
2347 }
2348
2349 //printf("Socket %u\n", newNetwork.tftpConn[i].sock);
2350
2351 errno = 0;
2352 newNetwork.tftpConn[i].addr.sin_family = AF_INET;
2353 newNetwork.tftpConn[i].addr.sin_addr.s_addr = newNetwork.listenServers[j];
2354 newNetwork.tftpConn[i].addr.sin_port = htons(newNetwork.listenPorts[j]);
2355 int nRet = bind(newNetwork.tftpConn[i].sock, (sockaddr*)&newNetwork.tftpConn[i].addr, sizeof(struct sockaddr_in));
2356
2357 if (nRet == SOCKET_ERROR || errno)
2358 {
2359 bindfailed = true;
2360 closesocket(newNetwork.tftpConn[i].sock);
2361 sprintf(logBuff, "%s Port %i bind failed", IP2String(tempbuff, newNetwork.listenServers[j]), newNetwork.listenPorts[j]);
2362 logMess(logBuff, 1);
2363 continue;
2364 }
2365
2366 newNetwork.tftpConn[i].loaded = true;
2367 newNetwork.tftpConn[i].ready = true;
2368 newNetwork.tftpConn[i].server = newNetwork.listenServers[j];
2369 newNetwork.tftpConn[i].port = newNetwork.listenPorts[j];
2370
2371 //printf("%d, %s created\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2372
2373 if (newNetwork.maxFD < newNetwork.tftpConn[i].sock)
2374 newNetwork.maxFD = newNetwork.tftpConn[i].sock;
2375
2376 if (!newNetwork.listenServers[j])
2377 break;
2378
2379 i++;
2380 }
2381 }
2382
2383 if (bindfailed)
2384 cfig.failureCount++;
2385 else
2386 cfig.failureCount = 0;
2387
2388 closeConn();
2389 memcpy(&network, &newNetwork, sizeof(data1));
2390
2391 //printf("%i %i %i\n", network.tftpConn[0].ready, network.dnsUdpConn[0].ready, network.dnsTcpConn[0].ready);
2392
2393 if (!network.tftpConn[0].ready)
2394 {
2395 sprintf(logBuff, "No Static Interface ready, Waiting...");
2396 logMess(logBuff, 1);
2397 continue;
2398 }
2399
2400 for (int i = 0; i < MAX_SERVERS && network.tftpConn[i].loaded; i++)
2401 {
2402 sprintf(logBuff, "Listening On: %s:%d", IP2String(tempbuff, network.tftpConn[i].server), network.tftpConn[i].port);
2403 logMess(logBuff, 1);
2404 }
2405
2406 network.ready = true;
2407
2408 } while (detectChange());
2409
2410 //printf("Exiting Init\n");
2411
2412 _endthread();
2413 return;
2414 }
2415
2416 bool detectChange()
2417 {
2418 if (!cfig.failureCount)
2419 {
2420 if (cfig.ifspecified)
2421 return false;
2422 }
2423
2424 MYDWORD eventWait = UINT_MAX;
2425
2426 if (cfig.failureCount)
2427 eventWait = 10000 * pow(2, cfig.failureCount);
2428
2429 OVERLAPPED overlap;
2430 MYDWORD ret;
2431 HANDLE hand = NULL;
2432 overlap.hEvent = WSACreateEvent();
2433
2434 ret = NotifyAddrChange(&hand, &overlap);
2435
2436 if (ret != NO_ERROR)
2437 {
2438 if (WSAGetLastError() != WSA_IO_PENDING)
2439 {
2440 printf("NotifyAddrChange error...%d\n", WSAGetLastError());
2441 return true;
2442 }
2443 }
2444
2445 if ( WaitForSingleObject(overlap.hEvent, eventWait) == WAIT_OBJECT_0 )
2446 WSACloseEvent(overlap.hEvent);
2447
2448 network.ready = false;
2449
2450 while (network.busy)
2451 Sleep(1000);
2452
2453 if (cfig.failureCount)
2454 {
2455 sprintf(logBuff, "Retrying failed Listening Interfaces..");
2456 logMess(logBuff, 1);
2457 }
2458 else
2459 {
2460 sprintf(logBuff, "Network changed, re-detecting Interfaces..");
2461 logMess(logBuff, 1);
2462 }
2463
2464 return true;
2465 }
2466
2467 /*
2468 void getInterfaces(data1 *network)
2469 {
2470 memset(network, 0, sizeof(data1));
2471
2472 SOCKET sd = WSASocket(PF_INET, SOCK_DGRAM, 0, 0, 0, 0);
2473
2474 if (sd == INVALID_SOCKET)
2475 return;
2476
2477 INTERFACE_INFO InterfaceList[MAX_SERVERS];
2478 unsigned long nBytesReturned;
2479
2480 if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
2481 sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
2482 return ;
2483
2484 int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
2485
2486 for (int i = 0; i < nNumInterfaces; ++i)
2487 {
2488 sockaddr_in *pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress);
2489 u_long nFlags = InterfaceList[i].iiFlags;
2490
2491 if (!(nFlags & IFF_POINTTOPOINT))
2492 {
2493 //printf("%s\n", IP2String(tempbuff, pAddress->sin_addr.S_un.S_addr));
2494 addServer(network->staticServers, pAddress->sin_addr.s_addr);
2495 }
2496 }
2497
2498 closesocket(sd);
2499 }
2500 */
2501
2502
2503 void getInterfaces(data1 *network)
2504 {
2505 memset(network, 0, sizeof(data1));
2506
2507 SOCKET sd = WSASocket(PF_INET, SOCK_DGRAM, 0, 0, 0, 0);
2508
2509 if (sd == INVALID_SOCKET)
2510 return;
2511
2512 INTERFACE_INFO InterfaceList[MAX_SERVERS];
2513 unsigned long nBytesReturned;
2514
2515 if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
2516 sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
2517 return ;
2518
2519 int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
2520
2521 for (int i = 0; i < nNumInterfaces; ++i)
2522 {
2523 sockaddr_in *pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress);
2524 u_long nFlags = InterfaceList[i].iiFlags;
2525
2526 if (pAddress->sin_addr.s_addr)
2527 {
2528 addServer(network->allServers, pAddress->sin_addr.s_addr);
2529
2530 if (!(nFlags & IFF_POINTTOPOINT) && (nFlags & IFF_UP))
2531 {
2532 addServer(network->staticServers, pAddress->sin_addr.s_addr);
2533 }
2534 }
2535 }
2536
2537 closesocket(sd);
2538 }
2539
2540
2541 bool addServer(MYDWORD *array, MYDWORD ip)
2542 {
2543 for (MYBYTE i = 0; i < MAX_SERVERS; i++)
2544 {
2545 if (!ip || array[i] == ip)
2546 return 0;
2547 else if (!array[i])
2548 {
2549 array[i] = ip;
2550 return 1;
2551 }
2552 }
2553 return 0;
2554 }
2555
2556 MYDWORD *findServer(MYDWORD *array, MYDWORD ip)
2557 {
2558 if (ip)
2559 {
2560 for (MYBYTE i = 0; i < MAX_SERVERS && array[i]; i++)
2561 {
2562 if (array[i] == ip)
2563 return &(array[i]);
2564 }
2565 }
2566 return 0;
2567 }
2568
2569 void logMess(char *logBuff, MYBYTE logLevel)
2570 {
2571 WaitForSingleObject(lEvent, INFINITE);
2572
2573 if (verbatim)
2574 printf("%s\n", logBuff);
2575 else if (cfig.logfile && logLevel <= cfig.logLevel)
2576 {
2577 time_t t = time(NULL);
2578 tm *ttm = localtime(&t);
2579
2580 if (ttm->tm_yday != loggingDay)
2581 {
2582 loggingDay = ttm->tm_yday;
2583 strftime(extbuff, sizeof(extbuff), logFile, ttm);
2584 fprintf(cfig.logfile, "Logging Continued on file %s\n", extbuff);
2585 fclose(cfig.logfile);
2586 cfig.logfile = fopen(extbuff, "at");
2587
2588 if (cfig.logfile)
2589 {
2590 fprintf(cfig.logfile, "%s\n\n", sVersion);
2591 WritePrivateProfileString("InternetShortcut","URL", extbuff, lnkFile);
2592 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile);
2593 WritePrivateProfileString("InternetShortcut","IconFile", extbuff, lnkFile);
2594 }
2595 else
2596 return;
2597 }
2598
2599 strftime(extbuff, sizeof(extbuff), "%d-%b-%y %X", ttm);
2600 fprintf(cfig.logfile, "[%s] %s\n", extbuff, logBuff);
2601 fflush(cfig.logfile);
2602 }
2603 SetEvent(lEvent);
2604 }
2605
2606 void logMess(request *req, MYBYTE logLevel)
2607 {
2608 WaitForSingleObject(lEvent, INFINITE);
2609
2610 char tempbuff[256];
2611
2612 if (verbatim)
2613 {
2614 if (!req->serverError.errormessage[0])
2615 sprintf(req->serverError.errormessage, strerror(errno));
2616
2617 if (req->path[0])
2618 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);
2619 else
2620 printf("Client %s:%u, %s\n", IP2String(tempbuff, req->client.sin_addr.s_addr), ntohs(req->client.sin_port), req->serverError.errormessage);
2621 }
2622 else if (cfig.logfile && logLevel <= cfig.logLevel)
2623 {
2624 time_t t = time(NULL);
2625 tm *ttm = localtime(&t);
2626
2627 if (ttm->tm_yday != loggingDay)
2628 {
2629 loggingDay = ttm->tm_yday;
2630 strftime(extbuff, sizeof(extbuff), logFile, ttm);
2631 fprintf(cfig.logfile, "Logging Continued on file %s\n", extbuff);
2632 fclose(cfig.logfile);
2633 cfig.logfile = fopen(extbuff, "at");
2634
2635 if (cfig.logfile)
2636 {
2637 fprintf(cfig.logfile, "%s\n\n", sVersion);
2638 WritePrivateProfileString("InternetShortcut","URL", extbuff, lnkFile);
2639 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile);
2640 WritePrivateProfileString("InternetShortcut","IconFile", extbuff, lnkFile);
2641 }
2642 else
2643 return;
2644 }
2645
2646 strftime(extbuff, sizeof(extbuff), "%d-%b-%y %X", ttm);
2647
2648 if (req->path[0])
2649 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);
2650 else
2651 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);
2652
2653 fflush(cfig.logfile);
2654 }
2655 SetEvent(lEvent);
2656 }