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