1 /**************************************************************************
2 * Copyright (C) 2005 by Achal Dhir *
3 * achaldhir@gmail.com *
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. *
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. *
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 ***************************************************************************/
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
];
41 char notFileSep
= '/';
46 //ThreadPool Variables
51 BYTE currentServer
= UCHAR_MAX
;
57 SERVICE_STATUS serviceStatus
;
58 SERVICE_STATUS_HANDLE serviceStatusHandle
= 0;
59 HANDLE stopServiceEvent
= 0;
61 void WINAPI
ServiceControlHandler(DWORD controlCode
)
65 case SERVICE_CONTROL_INTERROGATE
:
68 case SERVICE_CONTROL_SHUTDOWN
:
69 case SERVICE_CONTROL_STOP
:
70 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
71 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
73 SetEvent(stopServiceEvent
);
76 case SERVICE_CONTROL_PAUSE
:
79 case SERVICE_CONTROL_CONTINUE
:
83 if (controlCode
>= 128 && controlCode
<= 255)
89 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
92 void WINAPI
ServiceMain(DWORD
/*argc*/, TCHAR
* /*argv*/[])
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;
102 serviceStatusHandle
= RegisterServiceCtrlHandler(serviceName
, ServiceControlHandler
);
104 if (serviceStatusHandle
)
106 serviceStatus
.dwCurrentState
= SERVICE_START_PENDING
;
107 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
117 stopServiceEvent
= CreateEvent(0, FALSE
, FALSE
, 0);
119 serviceStatus
.dwControlsAccepted
|= (SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
120 serviceStatus
.dwCurrentState
= SERVICE_RUNNING
;
121 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
127 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
128 FD_SET(cfig
.tftpConn
[i
].sock
, &readfds
);
130 int fdsReady
= select(cfig
.maxFD
, &readfds
, NULL
, NULL
, &tv
);
132 for (int i
= 0; fdsReady
> 0 && i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
134 if (FD_ISSET(cfig
.tftpConn
[i
].sock
, &readfds
))
136 WaitForSingleObject(sEvent
, INFINITE
);
140 if (!totalThreads
|| activeThreads
>= totalThreads
)
143 processRequest
, // thread function
144 0, // default security attributes
145 NULL
); // argument to thread function
150 WaitForSingleObject(sEvent
, INFINITE
);
156 while (WaitForSingleObject(stopServiceEvent
, 0) == WAIT_TIMEOUT
);
159 fclose(cfig
.logfile
);
161 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
162 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
164 sprintf(logBuff
, "Closing Network Connections...");
167 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
168 closesocket(cfig
.tftpConn
[i
].sock
);
172 sprintf(logBuff
, "TFTP Server Stopped !");
175 serviceStatus
.dwControlsAccepted
&= ~(SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
176 serviceStatus
.dwCurrentState
= SERVICE_STOPPED
;
177 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
178 CloseHandle(stopServiceEvent
);
179 stopServiceEvent
= 0;
185 SERVICE_TABLE_ENTRY serviceTable
[] =
187 {serviceName
, ServiceMain
},
191 StartServiceCtrlDispatcher(serviceTable
);
194 bool stopService(SC_HANDLE service
)
198 SERVICE_STATUS serviceStatus
;
199 QueryServiceStatus(service
, &serviceStatus
);
200 if (serviceStatus
.dwCurrentState
!= SERVICE_STOPPED
)
202 ControlService(service
, SERVICE_CONTROL_STOP
, &serviceStatus
);
203 printf("Stopping Service.");
204 for (int i
= 0; i
< 100; i
++)
206 QueryServiceStatus(service
, &serviceStatus
);
207 if (serviceStatus
.dwCurrentState
== SERVICE_STOPPED
)
225 void installService()
227 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE
);
229 if (serviceControlManager
)
231 SC_HANDLE service
= OpenService(serviceControlManager
,
232 serviceName
, SERVICE_QUERY_STATUS
);
235 printf("Service Already Exists..\n");
236 StartService(service
,0,NULL
);
237 CloseServiceHandle(service
);
241 TCHAR path
[ _MAX_PATH
+ 1 ];
242 if (GetModuleFileName(0, path
, sizeof(path
) / sizeof(path
[0])) > 0)
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
,
251 printf("Successfully installed.. !\n");
252 StartService(service
,0,NULL
);
253 CloseServiceHandle(service
);
256 printf("Installation Failed..\n");
259 CloseServiceHandle(serviceControlManager
);
265 void uninstallService()
267 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
269 if (serviceControlManager
)
271 SC_HANDLE service
= OpenService(serviceControlManager
,
272 serviceName
, SERVICE_QUERY_STATUS
| SERVICE_STOP
| DELETE
);
275 if (stopService(service
))
277 DeleteService(service
);
278 printf("Successfully Removed !\n");
281 printf("Failed to Stop Service..\n");
283 CloseServiceHandle(service
);
286 CloseServiceHandle(serviceControlManager
);
292 void printWindowsError()
294 DWORD dw
= GetLastError();
301 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
302 FORMAT_MESSAGE_FROM_SYSTEM
|
303 FORMAT_MESSAGE_IGNORE_INSERTS
,
306 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
310 printf("Error: %p\nPress Enter..\n", lpMsgBuf
);
315 int main(int argc
, TCHAR
* argv
[])
318 osvi
.dwOSVersionInfoSize
= sizeof(osvi
);
319 bool result
= GetVersionEx(&osvi
);
321 if (result
&& osvi
.dwPlatformId
>= VER_PLATFORM_WIN32_NT
)
323 if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-i")) == 0)
325 else if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-u")) == 0)
327 else if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-v")) == 0)
329 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
330 bool serviceStopped
= true;
332 if (serviceControlManager
)
334 SC_HANDLE service
= OpenService(serviceControlManager
,
335 serviceName
, SERVICE_QUERY_STATUS
| SERVICE_STOP
);
338 serviceStopped
= stopService(service
);
339 CloseServiceHandle(service
);
341 CloseServiceHandle(serviceControlManager
);
349 printf("Failed to Stop Service\n");
354 else if (argc
== 1 || lstrcmpi(argv
[1], TEXT("-v")) == 0)
357 printf("This option is not available on Windows95/98/ME\n");
372 printf("\naccepting requests..\n");
376 //printf("Active=%u Total=%u\n",activeThreads, totalThreads);
380 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
381 FD_SET(cfig
.tftpConn
[i
].sock
, &readfds
);
383 fdsReady
= select(cfig
.maxFD
, &readfds
, NULL
, NULL
, &tv
);
386 // printf("%s\n", strerror(errno));
388 for (int i
= 0; fdsReady
> 0 && i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
390 if (FD_ISSET(cfig
.tftpConn
[i
].sock
, &readfds
))
392 //printf("Request Waiting\n");
394 WaitForSingleObject(sEvent
, INFINITE
);
398 if (!totalThreads
|| activeThreads
>= totalThreads
)
401 processRequest
, // thread function
402 0, // default security attributes
403 NULL
); // argument to thread function
407 //printf("thread signalled=%u\n",SetEvent(tEvent));
409 WaitForSingleObject(sEvent
, INFINITE
);
417 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
418 closesocket(cfig
.tftpConn
[i
].sock
);
423 void processRequest(void *lpParam
)
425 //printf("New Thread %u\n",GetCurrentThreadId());
429 WaitForSingleObject(cEvent
, INFINITE
);
435 WaitForSingleObject(tEvent
, INFINITE
);
436 //printf("In Thread %u\n",GetCurrentThreadId());
438 WaitForSingleObject(cEvent
, INFINITE
);
442 if (currentServer
>= MAX_SERVERS
|| !cfig
.tftpConn
[currentServer
].port
)
445 req
.attempt
= UCHAR_MAX
;
449 memset(&req
, 0, sizeof(request
));
450 req
.sock
= INVALID_SOCKET
;
452 req
.clientsize
= sizeof(req
.client
);
453 req
.sockInd
= currentServer
;
454 currentServer
= UCHAR_MAX
;
455 req
.knock
= cfig
.tftpConn
[req
.sockInd
].sock
;
457 if (req
.knock
== INVALID_SOCKET
)
460 req
.attempt
= UCHAR_MAX
;
465 req
.bytesRecd
= recvfrom(req
.knock
, (char*)&req
.mesin
, sizeof(message
), 0, (sockaddr
*)&req
.client
, &req
.clientsize
);
466 errno
= WSAGetLastError();
468 //printf("socket Signalled=%u\n",SetEvent(sEvent));
471 if (!errno
&& req
.bytesRecd
> 0)
473 if (cfig
.hostRanges
[0].rangeStart
)
475 DWORD iip
= ntohl(req
.client
.sin_addr
.s_addr
);
476 bool allowed
= false;
478 for (int j
= 0; j
<= 32 && cfig
.hostRanges
[j
].rangeStart
; j
++)
480 if (iip
>= cfig
.hostRanges
[j
].rangeStart
&& iip
<= cfig
.hostRanges
[j
].rangeEnd
)
489 req
.serverError
.opcode
= htons(5);
490 req
.serverError
.errorcode
= htons(2);
491 strcpy(req
.serverError
.errormessage
, "Access Denied");
493 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
494 req
.attempt
= UCHAR_MAX
;
499 if ((htons(req
.mesin
.opcode
) == 5))
501 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.clientError
.errorcode
), req
.clientError
.errormessage
);
503 req
.attempt
= UCHAR_MAX
;
506 else if (htons(req
.mesin
.opcode
) != 1 && htons(req
.mesin
.opcode
) != 2)
508 req
.serverError
.opcode
= htons(5);
509 req
.serverError
.errorcode
= htons(5);
510 sprintf(req
.serverError
.errormessage
, "Unknown Transfer Id");
512 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
513 req
.attempt
= UCHAR_MAX
;
519 sprintf(req
.serverError
.errormessage
, "Communication Error");
521 req
.attempt
= UCHAR_MAX
;
526 req
.timeout
= timeout
;
527 req
.expiry
= time(NULL
) + req
.timeout
;
528 bool fetchAck
= false;
530 req
.sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
532 if (req
.sock
== INVALID_SOCKET
)
534 req
.serverError
.opcode
= htons(5);
535 req
.serverError
.errorcode
= htons(0);
536 strcpy(req
.serverError
.errormessage
, "Thread Socket Creation Error");
537 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
539 req
.attempt
= UCHAR_MAX
;
544 service
.sin_family
= AF_INET
;
545 service
.sin_addr
.s_addr
= cfig
.tftpConn
[req
.sockInd
].server
;
549 for (WORD comport
= cfig
.minport
; ; comport
++)
551 service
.sin_port
= htons(comport
);
553 if (comport
> cfig
.maxport
)
555 req
.serverError
.opcode
= htons(5);
556 req
.serverError
.errorcode
= htons(0);
557 strcpy(req
.serverError
.errormessage
, "No port is free");
558 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
560 req
.attempt
= UCHAR_MAX
;
563 else if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
571 service
.sin_port
= 0;
573 if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
575 strcpy(req
.serverError
.errormessage
, "Thread failed to bind");
576 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
578 req
.attempt
= UCHAR_MAX
;
582 if (req
.attempt
>= 3)
585 if (connect(req
.sock
, (sockaddr
*)&req
.client
, req
.clientsize
) == -1)
587 req
.serverError
.opcode
= htons(5);
588 req
.serverError
.errorcode
= htons(0);
589 strcpy(req
.serverError
.errormessage
, "Connect Failed");
590 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
592 req
.attempt
= UCHAR_MAX
;
596 //sprintf(req.serverError.errormessage, "In Temp, Socket");
599 char *inPtr
= req
.mesin
.buffer
;
600 *(inPtr
+ (req
.bytesRecd
- 3)) = 0;
601 req
.filename
= inPtr
;
603 if (!strlen(req
.filename
) || strlen(req
.filename
) > UCHAR_MAX
)
605 req
.serverError
.opcode
= htons(5);
606 req
.serverError
.errorcode
= htons(4);
607 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Filename");
608 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
609 req
.attempt
= UCHAR_MAX
;
614 inPtr
+= strlen(inPtr
) + 1;
617 if (!strlen(req
.mode
) || strlen(req
.mode
) > 25)
619 req
.serverError
.opcode
= htons(5);
620 req
.serverError
.errorcode
= htons(4);
621 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Mode");
622 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
623 req
.attempt
= UCHAR_MAX
;
628 inPtr
+= strlen(inPtr
) + 1;
630 for (DWORD i
= 0; i
< strlen(req
.filename
); i
++)
631 if (req
.filename
[i
] == notFileSep
)
632 req
.filename
[i
] = fileSep
;
636 tempbuff
[2] = fileSep
;
639 if (strstr(req
.filename
, tempbuff
))
641 req
.serverError
.opcode
= htons(5);
642 req
.serverError
.errorcode
= htons(2);
643 strcpy(req
.serverError
.errormessage
, "Access violation");
644 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
646 req
.attempt
= UCHAR_MAX
;
650 if (req
.filename
[0] == fileSep
)
653 if (!cfig
.homes
[0].alias
[0])
655 if (strlen(cfig
.homes
[0].target
) + strlen(req
.filename
) >= sizeof(req
.path
))
657 req
.serverError
.opcode
= htons(5);
658 req
.serverError
.errorcode
= htons(4);
659 sprintf(req
.serverError
.errormessage
, "Filename too large");
660 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
662 req
.attempt
= UCHAR_MAX
;
666 strcpy(req
.path
, cfig
.homes
[0].target
);
667 strcat(req
.path
, req
.filename
);
671 char *bname
= strchr(req
.filename
, fileSep
);
680 req
.serverError
.opcode
= htons(5);
681 req
.serverError
.errorcode
= htons(2);
682 sprintf(req
.serverError
.errormessage
, "Missing directory/alias");
683 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
685 req
.attempt
= UCHAR_MAX
;
689 for (int i
= 0; i
< 8; i
++)
691 //printf("%s=%i\n", req.filename, cfig.homes[i].alias[0]);
692 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(req
.filename
, cfig
.homes
[i
].alias
))
694 if (strlen(cfig
.homes
[i
].target
) + strlen(bname
) >= sizeof(req
.path
))
696 req
.serverError
.opcode
= htons(5);
697 req
.serverError
.errorcode
= htons(4);
698 sprintf(req
.serverError
.errormessage
, "Filename too large");
699 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
701 req
.attempt
= UCHAR_MAX
;
705 strcpy(req
.path
, cfig
.homes
[i
].target
);
706 strcat(req
.path
, bname
);
709 else if (i
== 7 || !cfig
.homes
[i
].alias
[0])
711 req
.serverError
.opcode
= htons(5);
712 req
.serverError
.errorcode
= htons(2);
713 sprintf(req
.serverError
.errormessage
, "No such directory/alias %s", req
.filename
);
714 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
716 req
.attempt
= UCHAR_MAX
;
722 if (req
.attempt
>= 3)
725 if (ntohs(req
.mesin
.opcode
) == 1)
729 req
.serverError
.opcode
= htons(5);
730 req
.serverError
.errorcode
= htons(2);
731 strcpy(req
.serverError
.errormessage
, "GET Access Denied");
733 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
734 req
.attempt
= UCHAR_MAX
;
744 if (!strcasecmp(tmp
, "blksize"))
746 tmp
+= strlen(tmp
) + 1;
747 DWORD val
= atol(tmp
);
751 else if (val
> blksize
)
758 tmp
+= strlen(tmp
) + 1;
764 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
765 req
.file
= fopen(req
.path
, "rt");
767 req
.file
= fopen(req
.path
, "rb");
769 if (errno
|| !req
.file
)
771 req
.serverError
.opcode
= htons(5);
772 req
.serverError
.errorcode
= htons(1);
773 strcpy(req
.serverError
.errormessage
, "File not found or No Access");
775 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
776 req
.attempt
= UCHAR_MAX
;
780 setvbuf(req
.file
, NULL
, _IOFBF
, req
.blksize
);
784 if (!cfig
.fileWrite
&& !cfig
.fileOverwrite
)
786 req
.serverError
.opcode
= htons(5);
787 req
.serverError
.errorcode
= htons(2);
788 strcpy(req
.serverError
.errormessage
, "PUT Access Denied");
789 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
791 req
.attempt
= UCHAR_MAX
;
795 req
.file
= fopen(req
.path
, "rb");
802 if (!cfig
.fileOverwrite
)
804 req
.serverError
.opcode
= htons(5);
805 req
.serverError
.errorcode
= htons(6);
806 strcpy(req
.serverError
.errormessage
, "File already exists");
807 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
809 req
.attempt
= UCHAR_MAX
;
813 else if (!cfig
.fileWrite
)
815 req
.serverError
.opcode
= htons(5);
816 req
.serverError
.errorcode
= htons(2);
817 strcpy(req
.serverError
.errormessage
, "Create File Access Denied");
818 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
820 req
.attempt
= UCHAR_MAX
;
826 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
827 req
.file
= fopen(req
.path
, "wt");
829 req
.file
= fopen(req
.path
, "wb");
831 if (errno
|| !req
.file
)
833 req
.serverError
.opcode
= htons(5);
834 req
.serverError
.errorcode
= htons(2);
835 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
836 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
838 req
.attempt
= UCHAR_MAX
;
846 char *outPtr
= req
.mesout
.buffer
;
847 req
.mesout
.opcode
= htons(6);
851 //printf("%s\n", inPtr);
852 if (!strcasecmp(inPtr
, "blksize"))
854 strcpy(outPtr
, inPtr
);
855 outPtr
+= strlen(outPtr
) + 1;
856 inPtr
+= strlen(inPtr
) + 1;
861 else if (val
> blksize
)
865 sprintf(outPtr
, "%lu", val
);
866 outPtr
+= strlen(outPtr
) + 1;
868 else if (!strcasecmp(inPtr
, "tsize"))
870 strcpy(outPtr
, inPtr
);
871 outPtr
+= strlen(outPtr
) + 1;
872 inPtr
+= strlen(inPtr
) + 1;
874 if (ntohs(req
.mesin
.opcode
) == 1)
876 if (!fseek(req
.file
, 0, SEEK_END
))
878 if (ftell(req
.file
) >= 0)
880 req
.tsize
= ftell(req
.file
);
881 sprintf(outPtr
, "%lu", req
.tsize
);
882 outPtr
+= strlen(outPtr
) + 1;
886 req
.serverError
.opcode
= htons(5);
887 req
.serverError
.errorcode
= htons(2);
888 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
889 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
891 req
.attempt
= UCHAR_MAX
;
897 req
.serverError
.opcode
= htons(5);
898 req
.serverError
.errorcode
= htons(2);
899 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
900 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
902 req
.attempt
= UCHAR_MAX
;
909 sprintf(outPtr
, "%lu", req
.tsize
);
910 outPtr
+= strlen(outPtr
) + 1;
913 else if (!strcasecmp(inPtr
, "timeout"))
915 strcpy(outPtr
, inPtr
);
916 outPtr
+= strlen(outPtr
) + 1;
917 inPtr
+= strlen(inPtr
) + 1;
922 else if (val
> UCHAR_MAX
)
926 req
.expiry
= time(NULL
) + req
.timeout
;
927 sprintf(outPtr
, "%lu", val
);
928 outPtr
+= strlen(outPtr
) + 1;
931 inPtr
+= strlen(inPtr
) + 1;
932 //printf("=%u\n", val);
935 if (req
.attempt
>= 3)
939 req
.bytesReady
= (DWORD
)outPtr
- (DWORD
)&req
.mesout
;
940 //printf("Bytes Ready=%u\n", req.bytesReady);
941 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
942 errno
= WSAGetLastError();
944 else if (htons(req
.mesin
.opcode
) == 2)
946 req
.acout
.opcode
= htons(4);
947 req
.acout
.block
= htons(0);
950 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
951 errno
= WSAGetLastError();
956 sprintf(req
.serverError
.errormessage
, "Communication Error");
958 req
.attempt
= UCHAR_MAX
;
961 else if (ntohs(req
.mesin
.opcode
) == 1)
964 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
965 req
.pkt
[1] = (packet
*)calloc(1, req
.blksize
+ 4);
967 if (errno
|| !req
.pkt
[0] || !req
.pkt
[1])
969 sprintf(req
.serverError
.errormessage
, "Memory Error");
971 req
.attempt
= UCHAR_MAX
;
975 long ftellLoc
= ftell(req
.file
);
979 if (fseek(req
.file
, 0, SEEK_SET
))
981 req
.serverError
.opcode
= htons(5);
982 req
.serverError
.errorcode
= htons(2);
983 strcpy(req
.serverError
.errormessage
, "File Access Error");
984 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
986 req
.attempt
= UCHAR_MAX
;
990 else if (ftellLoc
< 0)
992 req
.serverError
.opcode
= htons(5);
993 req
.serverError
.errorcode
= htons(2);
994 strcpy(req
.serverError
.errormessage
, "File Access Error");
995 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
997 req
.attempt
= UCHAR_MAX
;
1002 req
.pkt
[0]->opcode
= htons(3);
1003 req
.pkt
[0]->block
= htons(1);
1004 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1008 req
.serverError
.opcode
= htons(5);
1009 req
.serverError
.errorcode
= htons(2);
1010 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1011 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1013 req
.attempt
= UCHAR_MAX
;
1017 if (req
.bytesRead
[0] == req
.blksize
)
1019 req
.pkt
[1]->opcode
= htons(3);
1020 req
.pkt
[1]->block
= htons(2);
1021 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1022 if (req
.bytesRead
[1] < req
.blksize
)
1036 req
.serverError
.opcode
= htons(5);
1037 req
.serverError
.errorcode
= htons(2);
1038 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1039 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1041 req
.attempt
= UCHAR_MAX
;
1045 while (req
.attempt
<= 3)
1049 FD_ZERO(&req
.readfds
);
1052 FD_SET(req
.sock
, &req
.readfds
);
1053 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1055 if (FD_ISSET(req
.sock
, &req
.readfds
))
1058 req
.bytesRecd
= recv(req
.sock
, (char*)&req
.mesin
, sizeof(message
), 0);
1059 errno
= WSAGetLastError();
1060 if (req
.bytesRecd
<= 0 || errno
)
1062 sprintf(req
.serverError
.errormessage
, "Communication Error");
1064 req
.attempt
= UCHAR_MAX
;
1067 else if(req
.bytesRecd
>= 4 && ntohs(req
.mesin
.opcode
) == 4)
1069 if (ntohs(req
.acin
.block
) == req
.block
)
1075 else if (req
.expiry
> time(NULL
))
1080 else if (ntohs(req
.mesin
.opcode
) == 5)
1082 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
);
1084 req
.attempt
= UCHAR_MAX
;
1089 req
.serverError
.opcode
= htons(5);
1090 req
.serverError
.errorcode
= htons(4);
1091 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.mesin
.opcode
));
1092 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1094 req
.attempt
= UCHAR_MAX
;
1098 else if (req
.expiry
> time(NULL
))
1111 if (req
.attempt
>= 3)
1113 req
.serverError
.opcode
= htons(5);
1114 req
.serverError
.errorcode
= htons(0);
1116 if (req
.fblock
&& !req
.block
)
1117 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1119 strcpy(req
.serverError
.errormessage
, "Timeout");
1122 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1123 req
.attempt
= UCHAR_MAX
;
1126 else if (!req
.fblock
)
1129 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1130 errno
= WSAGetLastError();
1133 sprintf(req
.serverError
.errormessage
, "Communication Error");
1135 req
.attempt
= UCHAR_MAX
;
1138 req
.expiry
= time(NULL
) + req
.timeout
;
1140 else if (ntohs(req
.pkt
[0]->block
) == req
.block
)
1143 send(req
.sock
, (const char*)req
.pkt
[0], req
.bytesRead
[0] + 4, 0);
1144 errno
= WSAGetLastError();
1147 sprintf(req
.serverError
.errormessage
, "Communication Error");
1149 req
.attempt
= UCHAR_MAX
;
1152 req
.expiry
= time(NULL
) + req
.timeout
;
1156 req
.tblock
= ntohs(req
.pkt
[1]->block
) + 1;
1157 if (req
.tblock
== req
.block
)
1159 req
.pkt
[1]->block
= htons(++req
.tblock
);
1160 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1164 req
.serverError
.opcode
= htons(5);
1165 req
.serverError
.errorcode
= htons(4);
1166 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1167 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1169 req
.attempt
= UCHAR_MAX
;
1172 else if (req
.bytesRead
[1] < req
.blksize
)
1180 else if (ntohs(req
.pkt
[1]->block
) == req
.block
)
1183 send(req
.sock
, (const char*)req
.pkt
[1], req
.bytesRead
[1] + 4, 0);
1184 errno
= WSAGetLastError();
1187 sprintf(req
.serverError
.errormessage
, "Communication Error");
1189 req
.attempt
= UCHAR_MAX
;
1193 req
.expiry
= time(NULL
) + req
.timeout
;
1197 req
.tblock
= ntohs(req
.pkt
[0]->block
) + 1;
1198 if (req
.tblock
== req
.block
)
1200 req
.pkt
[0]->block
= htons(++req
.tblock
);
1201 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1204 req
.serverError
.opcode
= htons(5);
1205 req
.serverError
.errorcode
= htons(4);
1206 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1207 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1209 req
.attempt
= UCHAR_MAX
;
1212 else if (req
.bytesRead
[0] < req
.blksize
)
1222 sprintf(req
.serverError
.errormessage
, "%lu Blocks Served", req
.fblock
- 1);
1224 req
.attempt
= UCHAR_MAX
;
1229 else if (ntohs(req
.mesin
.opcode
) == 2)
1232 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1234 if (errno
|| !req
.pkt
[0])
1236 sprintf(req
.serverError
.errormessage
, "Memory Error");
1238 req
.attempt
= UCHAR_MAX
;
1242 while (req
.attempt
<= 3)
1244 FD_ZERO(&req
.readfds
);
1247 FD_SET(req
.sock
, &req
.readfds
);
1248 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1250 if (FD_ISSET(req
.sock
, &req
.readfds
))
1253 req
.bytesRecd
= recv(req
.sock
, (char*)req
.pkt
[0], req
.blksize
+ 4, 0);
1254 errno
= WSAGetLastError();
1258 sprintf(req
.serverError
.errormessage
, "Communication Error");
1260 req
.attempt
= UCHAR_MAX
;
1267 if (req
.bytesRecd
>= 4)
1269 if (ntohs(req
.pkt
[0]->opcode
) == 3)
1271 req
.tblock
= req
.block
+ 1;
1273 if (ntohs(req
.pkt
[0]->block
) == req
.tblock
)
1275 req
.acout
.opcode
= htons(4);
1276 req
.acout
.block
= req
.pkt
[0]->block
;
1280 req
.expiry
= time(NULL
) + req
.timeout
;
1283 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1284 errno
= WSAGetLastError();
1288 sprintf(req
.serverError
.errormessage
, "Communication Error");
1290 req
.attempt
= UCHAR_MAX
;
1294 if (req
.bytesRecd
> 4)
1297 if (fwrite(&req
.pkt
[0]->buffer
, req
.bytesRecd
- 4, 1, req
.file
) != 1 || errno
)
1299 req
.serverError
.opcode
= htons(5);
1300 req
.serverError
.errorcode
= htons(3);
1301 strcpy(req
.serverError
.errormessage
, "Disk full or allocation exceeded");
1302 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1304 req
.attempt
= UCHAR_MAX
;
1313 if ((WORD
)req
.bytesRecd
< req
.blksize
+ 4)
1317 sprintf(req
.serverError
.errormessage
, "%lu Blocks Received", req
.fblock
);
1319 req
.attempt
= UCHAR_MAX
;
1323 else if (req
.expiry
> time(NULL
))
1325 else if (req
.attempt
>= 3)
1327 req
.serverError
.opcode
= htons(5);
1328 req
.serverError
.errorcode
= htons(0);
1330 if (req
.fblock
&& !req
.block
)
1331 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1333 strcpy(req
.serverError
.errormessage
, "Timeout");
1336 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1337 req
.attempt
= UCHAR_MAX
;
1342 req
.expiry
= time(NULL
) + req
.timeout
;
1344 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1345 errno
= WSAGetLastError();
1350 sprintf(req
.serverError
.errormessage
, "Communication Error");
1352 req
.attempt
= UCHAR_MAX
;
1357 else if (req
.bytesRecd
> (int)sizeof(message
))
1359 req
.serverError
.opcode
= htons(5);
1360 req
.serverError
.errorcode
= htons(4);
1361 sprintf(req
.serverError
.errormessage
, "Error: Incoming Packet too large");
1362 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1364 req
.attempt
= UCHAR_MAX
;
1367 else if (ntohs(req
.pkt
[0]->opcode
) == 5)
1369 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.pkt
[0]->block
), &req
.pkt
[0]->buffer
);
1371 req
.attempt
= UCHAR_MAX
;
1376 req
.serverError
.opcode
= htons(5);
1377 req
.serverError
.errorcode
= htons(4);
1378 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.pkt
[0]->opcode
));
1379 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1381 req
.attempt
= UCHAR_MAX
;
1385 else if (req
.expiry
> time(NULL
))
1387 else if (req
.attempt
>= 3)
1389 req
.serverError
.opcode
= htons(5);
1390 req
.serverError
.errorcode
= htons(0);
1392 if (req
.fblock
&& !req
.block
)
1393 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1395 strcpy(req
.serverError
.errormessage
, "Timeout");
1398 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1399 req
.attempt
= UCHAR_MAX
;
1404 req
.expiry
= time(NULL
) + req
.timeout
;
1406 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1407 errno
= WSAGetLastError();
1412 sprintf(req
.serverError
.errormessage
, "Communication Error");
1414 req
.attempt
= UCHAR_MAX
;
1421 while (cleanReq(&req
));
1423 WaitForSingleObject(cEvent
, INFINITE
);
1427 //printf("Thread %u Killed\n",GetCurrentThreadId());
1432 bool cleanReq(request
* req
)
1434 //printf("cleaning\n");
1439 if (!(req
->sock
== INVALID_SOCKET
))
1442 closesocket(req
->sock
);
1451 WaitForSingleObject(cEvent
, INFINITE
);
1455 //printf("cleaned\n");
1457 return (totalThreads
<= minThreads
);
1460 char* myGetToken(char* buff
, BYTE index
)
1469 buff
+= strlen(buff
) + 1;
1475 WORD
myTokenize(char *target
, char *source
, char *sep
, bool whiteSep
)
1483 if (sep
&& sep
[0] && strchr(sep
, (*source
)))
1489 else if (whiteSep
&& *source
<= 32)
1516 //printf("%s\n", target);
1521 char* myTrim(char *target
, char *source
)
1523 while ((*source
) && (*source
) <= 32)
1528 for (; i
< 511 && source
[i
]; i
++)
1529 target
[i
] = source
[i
];
1531 target
[i
] = source
[i
];
1534 for (; i
>= 0 && target
[i
] <= 32; i
--)
1540 void mySplit(char *name
, char *value
, char *source
, char splitChar
)
1546 for (; source
[i
] && j
<= 510 && source
[i
] != splitChar
; i
++, j
++)
1548 name
[j
] = source
[i
];
1554 for (; k
<= 510 && source
[i
]; i
++, k
++)
1556 value
[k
] = source
[i
];
1564 myTrim(value
, value
);
1565 //printf("%s %s\n", name, value);
1568 bool getSection(char *sectionName
, char *buffer
, BYTE serial
, char *fileName
)
1570 //printf("%s=%s\n",fileName,sectionName);
1572 sprintf(section
, "[%s]", sectionName
);
1574 FILE *f
= fopen(fileName
, "rt");
1580 while (fgets(buff
, 511, f
))
1585 if (strstr(buff
, section
) == buff
)
1588 if (found
== serial
)
1590 //printf("%s=%s\n",fileName,sectionName);
1591 while (fgets(buff
, 511, f
))
1595 if (strstr(buff
, "[") == buff
)
1598 if ((*buff
) >= '0' && (*buff
) <= '9' || (*buff
) >= 'A' && (*buff
) <= 'Z' || (*buff
) >= 'a' && (*buff
) <= 'z' || ((*buff
) && strchr("/\\?*", (*buff
))))
1600 buffer
+= sprintf(buffer
, "%s", buff
);
1613 return (found
== serial
);
1616 char *IP2String(char *target
, DWORD ip
)
1620 sprintf(target
, "%u.%u.%u.%u", inaddr
.octate
[0], inaddr
.octate
[1], inaddr
.octate
[2], inaddr
.octate
[3]);
1624 bool isIP(char *string
)
1628 for (; *string
; string
++)
1630 if (*string
== '.' && *(string
+ 1) != '.')
1632 else if (*string
< '0' || *string
> '9')
1642 char *myUpper(char *string
)
1644 char diff
= 'a' - 'A';
1645 WORD len
= strlen(string
);
1646 for (int i
= 0; i
< len
; i
++)
1647 if (string
[i
] >= 'a' && string
[i
] <= 'z')
1652 char *myLower(char *string
)
1654 char diff
= 'a' - 'A';
1655 WORD len
= strlen(string
);
1656 for (int i
= 0; i
< len
; i
++)
1657 if (string
[i
] >= 'A' && string
[i
] <= 'Z')
1664 memset(&cfig
, 0, sizeof(cfig
));
1666 GetModuleFileName(NULL
, iniFile
, MAX_PATH
);
1667 char *iniFileExt
= strrchr(iniFile
, '.');
1668 strcpy(iniFileExt
, ".ini");
1669 GetModuleFileName(NULL
, logFile
, MAX_PATH
);
1670 iniFileExt
= strrchr(logFile
, '.');
1671 strcpy(iniFileExt
, ".log");
1680 printf("%s\n\n", sVersion
);
1682 else if (getSection("LOGGING", iniStr
, 1, iniFile
))
1684 char *iniStrPtr
= myGetToken(iniStr
, 0);
1686 if (!iniStrPtr
[0] || !strcasecmp(iniStrPtr
, "None"))
1688 else if (!strcasecmp(iniStrPtr
, "Errors"))
1690 else if (!strcasecmp(iniStrPtr
, "All"))
1692 else if (!strcasecmp(iniStrPtr
, "Debug"))
1695 cfig
.logLevel
= UCHAR_MAX
;
1698 if (!verbatim
&& cfig
.logLevel
)
1700 cfig
.logfile
= fopen(logFile
, "wt");
1704 fclose(cfig
.logfile
);
1705 cfig
.logfile
= fopen(logFile
, "at");
1706 fprintf(cfig
.logfile
, "%s\n", sVersion
);
1710 if (cfig
.logLevel
== UCHAR_MAX
)
1713 sprintf(logBuff
, "Section [LOGGING], Invalid Logging Level: %s, ignored", myGetToken(iniStr
, 0));
1714 logMess(logBuff
, 1);
1717 WORD wVersionRequested
= MAKEWORD(1, 1);
1718 WSAStartup(wVersionRequested
, &cfig
.wsaData
);
1720 if (cfig
.wsaData
.wVersion
!= wVersionRequested
)
1722 sprintf(logBuff
, "WSAStartup Error");
1723 logMess(logBuff
, 1);
1726 if (getSection("LISTEN-ON", iniStr
, 1, iniFile
))
1728 char *iniStrPtr
= myGetToken(iniStr
, 0);
1730 for (int i
= 0; i
< MAX_SERVERS
&& iniStrPtr
[0]; iniStrPtr
= myGetToken(iniStrPtr
, 1))
1732 strncpy(name
, iniStrPtr
, UCHAR_MAX
);
1734 char *dp
= strchr(name
, ':');
1742 DWORD ip
= my_inet_addr(name
);
1744 if (isIP(name
) && ip
)
1746 for (BYTE j
= 0; j
< MAX_SERVERS
; j
++)
1748 if (cfig
.servers
[j
] == ip
)
1750 else if (!cfig
.servers
[j
])
1752 cfig
.servers
[j
] = ip
;
1753 cfig
.ports
[j
] = port
;
1761 sprintf(logBuff
, "Warning: Section [LISTEN-ON], Invalid IP Address %s, ignored", iniStrPtr
);
1762 logMess(logBuff
, 1);
1767 if (getSection("HOME", iniStr
, 1, iniFile
))
1769 char *iniStrPtr
= myGetToken(iniStr
, 0);
1770 for (; iniStrPtr
[0]; iniStrPtr
= myGetToken(iniStrPtr
, 1))
1772 mySplit(name
, value
, iniStrPtr
, '=');
1775 if (!cfig
.homes
[0].alias
[0] && cfig
.homes
[0].target
[0])
1777 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", iniStrPtr
);
1778 logMess(logBuff
, 1);
1780 else if (strchr(name
, notFileSep
) || strchr(name
, fileSep
) || strchr(name
, '>') || strchr(name
, '<') || strchr(name
, '.'))
1782 sprintf(logBuff
, "Section [HOME], invalid chars in alias %s, entry ignored", name
);
1783 logMess(logBuff
, 1);
1785 else if (name
[0] && strlen(name
) < 64 && value
[0])
1787 for (int i
= 0; i
< 8; i
++)
1789 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(name
, cfig
.homes
[i
].alias
))
1791 sprintf(logBuff
, "Section [HOME], Duplicate Entry: %s ignored", iniStrPtr
);
1792 logMess(logBuff
, 1);
1795 else if (!cfig
.homes
[i
].alias
[0])
1797 strcpy(cfig
.homes
[i
].alias
, name
);
1798 strcpy(cfig
.homes
[i
].target
, value
);
1800 if (cfig
.homes
[i
].target
[strlen(cfig
.homes
[i
].target
) - 1] != fileSep
)
1802 tempbuff
[0] = fileSep
;
1804 strcat(cfig
.homes
[i
].target
, tempbuff
);
1813 sprintf(logBuff
, "Section [HOME], alias %s too large", name
);
1814 logMess(logBuff
, 1);
1817 else if (!cfig
.homes
[0].alias
[0] && !cfig
.homes
[0].target
[0])
1819 strcpy(cfig
.homes
[0].target
, name
);
1821 if (cfig
.homes
[0].target
[strlen(cfig
.homes
[0].target
) - 1] != fileSep
)
1823 tempbuff
[0] = fileSep
;
1825 strcat(cfig
.homes
[0].target
, tempbuff
);
1828 else if (cfig
.homes
[0].alias
[0])
1830 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", iniStrPtr
);
1831 logMess(logBuff
, 1);
1833 else if (cfig
.homes
[0].target
[0])
1835 sprintf(logBuff
, "Section [HOME], Duplicate Path: %s ignored", iniStrPtr
);
1836 logMess(logBuff
, 1);
1840 sprintf(logBuff
, "Section [HOME], missing = sign, Invalid Entry: %s ignored", iniStrPtr
);
1841 logMess(logBuff
, 1);
1846 if (!cfig
.homes
[0].target
[0])
1848 GetModuleFileName(NULL
, cfig
.homes
[0].target
, UCHAR_MAX
);
1849 char *iniFileExt
= strrchr(cfig
.homes
[0].target
, fileSep
);
1850 *(++iniFileExt
) = 0;
1853 cfig
.fileRead
= true;
1855 if (getSection("TFTP-OPTIONS", iniStr
, 1, iniFile
))
1857 char *iniStrPtr
= myGetToken(iniStr
, 0);
1858 for (;strlen(iniStrPtr
);iniStrPtr
= myGetToken(iniStrPtr
, 1))
1860 mySplit(name
, value
, iniStrPtr
, '=');
1863 if (!strcasecmp(name
, "blksize"))
1865 DWORD tblksize
= atol(value
);
1869 else if (tblksize
> USHRT_MAX
- 32)
1870 blksize
= USHRT_MAX
- 32;
1874 else if (!strcasecmp(name
, "threadpoolsize"))
1876 minThreads
= atol(value
);
1879 else if (minThreads
> 100)
1882 else if (!strcasecmp(name
, "timeout"))
1884 timeout
= atol(value
);
1887 else if (timeout
> UCHAR_MAX
)
1888 timeout
= UCHAR_MAX
;
1890 else if (!strcasecmp(name
, "Read"))
1892 if (strchr("Yy", *value
))
1893 cfig
.fileRead
= true;
1895 cfig
.fileRead
= false;
1897 else if (!strcasecmp(name
, "Write"))
1899 if (strchr("Yy", *value
))
1900 cfig
.fileWrite
= true;
1902 cfig
.fileWrite
= false;
1904 else if (!strcasecmp(name
, "Overwrite"))
1906 if (strchr("Yy", *value
))
1907 cfig
.fileOverwrite
= true;
1909 cfig
.fileOverwrite
= false;
1911 else if (!strcasecmp(name
, "port-range"))
1913 char *ptr
= strchr(value
, '-');
1917 cfig
.minport
= atol(value
);
1918 cfig
.maxport
= atol(++ptr
);
1920 if (cfig
.minport
< 1024 || cfig
.minport
>= USHRT_MAX
|| cfig
.maxport
< 1024 || cfig
.maxport
>= USHRT_MAX
|| cfig
.minport
> cfig
.maxport
)
1925 sprintf(logBuff
, "Invalid port range %s", value
);
1926 logMess(logBuff
, 1);
1931 sprintf(logBuff
, "Invalid port range %s", value
);
1932 logMess(logBuff
, 1);
1937 sprintf(logBuff
, "Warning: unknown option %s, ignored", name
);
1938 logMess(logBuff
, 1);
1944 if (getSection("ALLOWED-CLIENTS", iniStr
, 1, iniFile
))
1946 char *iniStrPtr
= myGetToken(iniStr
, 0);
1947 for (int i
= 0; i
< 32 && iniStrPtr
[0]; iniStrPtr
= myGetToken(iniStrPtr
, 1))
1951 mySplit(name
, value
, iniStrPtr
, '-');
1952 rs
= htonl(my_inet_addr(name
));
1955 re
= htonl(my_inet_addr(value
));
1959 if (rs
&& rs
!= INADDR_NONE
&& re
&& re
!= INADDR_NONE
&& rs
<= re
)
1961 cfig
.hostRanges
[i
].rangeStart
= rs
;
1962 cfig
.hostRanges
[i
].rangeEnd
= re
;
1967 sprintf(logBuff
, "Section [ALLOWED-CLIENTS] Invalid entry %s in ini file, ignored", iniStrPtr
);
1968 logMess(logBuff
, 1);
1973 // if (!cfig.servers[0])
1978 for (int j
= 0; j
< MAX_SERVERS
; j
++)
1980 if (j
&& !cfig
.servers
[j
])
1983 cfig
.tftpConn
[i
].sock
= socket(PF_INET
,
1987 if (cfig
.tftpConn
[i
].sock
== INVALID_SOCKET
)
1989 sprintf(logBuff
, "Failed to Create Socket");
1990 logMess(logBuff
, 1);
1994 cfig
.tftpConn
[i
].addr
.sin_family
= AF_INET
;
1999 cfig
.tftpConn
[i
].addr
.sin_addr
.s_addr
= cfig
.servers
[j
];
2000 cfig
.tftpConn
[i
].addr
.sin_port
= htons(cfig
.ports
[j
]);
2002 socklen_t nRet
= bind(cfig
.tftpConn
[i
].sock
,
2003 (sockaddr
*)&cfig
.tftpConn
[i
].addr
,
2004 sizeof(struct sockaddr_in
)
2007 if (nRet
== SOCKET_ERROR
)
2009 closesocket(cfig
.tftpConn
[i
].sock
);
2010 sprintf(logBuff
, "%s Port %u, bind failed", IP2String(tempbuff
, cfig
.servers
[j
]), cfig
.ports
[j
]);
2011 logMess(logBuff
, 1);
2015 if (cfig
.maxFD
< cfig
.tftpConn
[i
].sock
)
2016 cfig
.maxFD
= cfig
.tftpConn
[i
].sock
;
2018 cfig
.tftpConn
[i
].server
= cfig
.tftpConn
[i
].addr
.sin_addr
.s_addr
;
2019 cfig
.tftpConn
[i
].port
= htons(cfig
.tftpConn
[i
].addr
.sin_port
);
2025 if (!cfig
.tftpConn
[0].port
)
2027 sprintf(logBuff
, "no listening interfaces available, stopping..\nPress Enter to exit\n");
2028 logMess(logBuff
, 1);
2034 printf("starting TFTP...\n");
2038 sprintf(logBuff
, "starting TFTP service");
2039 logMess(logBuff
, 1);
2042 for (int i
= 0; i
< MAX_SERVERS
; i
++)
2043 if (cfig
.homes
[i
].target
[0])
2045 sprintf(logBuff
, "alias /%s is mapped to %s", cfig
.homes
[i
].alias
, cfig
.homes
[i
].target
);
2046 logMess(logBuff
, 1);
2049 if (cfig
.hostRanges
[0].rangeStart
)
2053 for (WORD i
= 0; i
<= sizeof(cfig
.hostRanges
) && cfig
.hostRanges
[i
].rangeStart
; i
++)
2055 sprintf(logBuff
, "%s", "permitted clients: ");
2056 sprintf(temp
, "%s-", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeStart
)));
2057 strcat(logBuff
, temp
);
2058 sprintf(temp
, "%s", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeEnd
)));
2059 strcat(logBuff
, temp
);
2060 logMess(logBuff
, 1);
2065 sprintf(logBuff
, "%s", "permitted clients: all");
2066 logMess(logBuff
, 1);
2071 sprintf(logBuff
, "server port range: %u-%u", cfig
.minport
, cfig
.maxport
);
2072 logMess(logBuff
, 1);
2076 sprintf(logBuff
, "server port range: all");
2077 logMess(logBuff
, 1);
2080 sprintf(logBuff
, "max blksize: %u", blksize
);
2081 logMess(logBuff
, 1);
2082 sprintf(logBuff
, "default blksize: %u", 512);
2083 logMess(logBuff
, 1);
2084 sprintf(logBuff
, "default timeout: %u", timeout
);
2085 logMess(logBuff
, 1);
2086 sprintf(logBuff
, "file read allowed: %s", cfig
.fileRead
? "Yes" : "No");
2087 logMess(logBuff
, 1);
2088 sprintf(logBuff
, "file create allowed: %s", cfig
.fileWrite
? "Yes" : "No");
2089 logMess(logBuff
, 1);
2090 sprintf(logBuff
, "file overwrite allowed: %s", cfig
.fileOverwrite
? "Yes" : "No");
2091 logMess(logBuff
, 1);
2095 sprintf(logBuff
, "logging: %s", cfig
.logLevel
> 1 ? "all" : "errors");
2096 logMess(logBuff
, 1);
2099 lEvent
= CreateEvent(
2100 NULL
, // default security descriptor
2101 FALSE
, // ManualReset
2103 TEXT("AchalTFTServerLogEvent")); // object name
2107 printf("CreateEvent error: %lu\n", GetLastError());
2110 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2112 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2113 logMess(logBuff
, 0);
2117 tEvent
= CreateEvent(
2118 NULL
, // default security descriptor
2119 FALSE
, // ManualReset
2121 TEXT("AchalTFTServerThreadEvent")); // object name
2125 printf("CreateEvent error: %lu\n", GetLastError());
2128 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2130 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2131 logMess(logBuff
, 0);
2135 sEvent
= CreateEvent(
2136 NULL
, // default security descriptor
2137 FALSE
, // ManualReset
2139 TEXT("AchalTFTServerSocketEvent")); // object name
2143 printf("CreateEvent error: %lu\n", GetLastError());
2146 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2148 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2149 logMess(logBuff
, 0);
2153 cEvent
= CreateEvent(
2154 NULL
, // default security descriptor
2155 FALSE
, // ManualReset
2157 TEXT("AchalTFTServerCountEvent")); // object name
2161 printf("CreateEvent error: %lu\n", GetLastError());
2164 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2166 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2167 logMess(logBuff
, 0);
2173 for (int i
= 0; i
< minThreads
; i
++)
2176 processRequest
, // thread function
2177 0, // default security attributes
2178 NULL
); // argument to thread function
2181 sprintf(logBuff
, "thread pool size: %u", minThreads
);
2182 logMess(logBuff
, 1);
2185 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
2187 sprintf(logBuff
, "listening on: %s:%i", IP2String(tempbuff
, cfig
.tftpConn
[i
].server
), cfig
.tftpConn
[i
].port
);
2188 logMess(logBuff
, 1);
2192 void logMess(char *logBuff
, BYTE logLevel
)
2194 WaitForSingleObject(lEvent
, INFINITE
);
2197 printf("%s\n", logBuff
);
2198 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2200 char currentTime
[32];
2201 time_t t
= time(NULL
);
2202 tm
*ttm
= localtime(&t
);
2203 strftime(currentTime
, sizeof(currentTime
), "%d-%b-%y %X", ttm
);
2204 fprintf(cfig
.logfile
, "[%s] %s\n", currentTime
, logBuff
);
2205 fflush(cfig
.logfile
);
2210 void logMess(request
*req
, BYTE logLevel
)
2212 WaitForSingleObject(lEvent
, INFINITE
);
2218 if (!req
->serverError
.errormessage
[0])
2219 sprintf(req
->serverError
.errormessage
, strerror(errno
));
2222 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
);
2224 printf("Client %s:%u, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2226 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2228 char currentTime
[32];
2229 time_t t
= time(NULL
);
2230 tm
*ttm
= localtime(&t
);
2231 strftime(currentTime
, sizeof(currentTime
), "%d-%b-%y %X", ttm
);
2234 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
);
2236 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
);
2238 fflush(cfig
.logfile
);