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