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 ***************************************************************************/
34 char serviceName
[] = "TFTPServer";
35 char displayName
[] = "Open TFTP Server, MultiThreaded";
36 char sVersion
[] = "Open TFTP Server MultiThreaded Version 1.64 Windows Built 2001";
37 char iniFile
[_MAX_PATH
];
38 char logFile
[_MAX_PATH
];
39 char lnkFile
[_MAX_PATH
];
44 char notFileSep
= '/';
45 MYWORD blksize
= 65464;
52 //ThreadPool Variables
57 MYBYTE currentServer
= UCHAR_MAX
;
58 MYWORD totalThreads
=0;
60 MYWORD activeThreads
=0;
63 SERVICE_STATUS serviceStatus
;
64 SERVICE_STATUS_HANDLE serviceStatusHandle
= 0;
65 HANDLE stopServiceEvent
= 0;
67 void WINAPI
ServiceControlHandler(DWORD controlCode
)
71 case SERVICE_CONTROL_INTERROGATE
:
74 case SERVICE_CONTROL_SHUTDOWN
:
75 case SERVICE_CONTROL_STOP
:
76 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
77 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
79 SetEvent(stopServiceEvent
);
82 case SERVICE_CONTROL_PAUSE
:
85 case SERVICE_CONTROL_CONTINUE
:
89 if (controlCode
>= 128 && controlCode
<= 255)
95 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
98 void WINAPI
ServiceMain(DWORD
/*argc*/, TCHAR
* /*argv*/[])
100 serviceStatus
.dwServiceType
= SERVICE_WIN32
;
101 serviceStatus
.dwCurrentState
= SERVICE_STOPPED
;
102 serviceStatus
.dwControlsAccepted
= 0;
103 serviceStatus
.dwWin32ExitCode
= NO_ERROR
;
104 serviceStatus
.dwServiceSpecificExitCode
= NO_ERROR
;
105 serviceStatus
.dwCheckPoint
= 0;
106 serviceStatus
.dwWaitHint
= 0;
108 serviceStatusHandle
= RegisterServiceCtrlHandler(serviceName
, ServiceControlHandler
);
110 if (serviceStatusHandle
)
112 serviceStatus
.dwCurrentState
= SERVICE_START_PENDING
;
113 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
118 if (_beginthread(init
, 0, 0) == 0)
122 sprintf(logBuff
, "Thread Creation Failed");
133 stopServiceEvent
= CreateEvent(0, FALSE
, FALSE
, 0);
135 serviceStatus
.dwControlsAccepted
|= (SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
136 serviceStatus
.dwCurrentState
= SERVICE_RUNNING
;
137 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
141 network
.busy
= false;
143 if (!network
.tftpConn
[0].ready
|| !network
.ready
)
151 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].ready
; i
++)
152 FD_SET(network
.tftpConn
[i
].sock
, &readfds
);
154 int fdsReady
= select(network
.maxFD
, &readfds
, NULL
, NULL
, &tv
);
156 for (int i
= 0; fdsReady
> 0 && i
< MAX_SERVERS
&& network
.tftpConn
[i
].ready
; i
++)
162 if (FD_ISSET(network
.tftpConn
[i
].sock
, &readfds
))
164 WaitForSingleObject(sEvent
, INFINITE
);
168 if (!totalThreads
|| activeThreads
>= totalThreads
)
171 processRequest
, // thread function
172 0, // default security attributes
173 NULL
); // argument to thread function
178 WaitForSingleObject(sEvent
, INFINITE
);
185 while (WaitForSingleObject(stopServiceEvent
, 0) == WAIT_TIMEOUT
);
187 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
188 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
190 sprintf(logBuff
, "Closing Network Connections...");
197 sprintf(logBuff
, "TFTP Server Stopped !\n");
202 fclose(cfig
.logfile
);
206 serviceStatus
.dwControlsAccepted
&= ~(SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
207 serviceStatus
.dwCurrentState
= SERVICE_STOPPED
;
208 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
209 CloseHandle(stopServiceEvent
);
210 stopServiceEvent
= 0;
216 SERVICE_TABLE_ENTRY serviceTable
[] =
218 {serviceName
, ServiceMain
},
222 StartServiceCtrlDispatcher(serviceTable
);
225 bool stopService(SC_HANDLE service
)
229 SERVICE_STATUS serviceStatus
;
230 QueryServiceStatus(service
, &serviceStatus
);
231 if (serviceStatus
.dwCurrentState
!= SERVICE_STOPPED
)
233 ControlService(service
, SERVICE_CONTROL_STOP
, &serviceStatus
);
234 printf("Stopping Service.");
235 for (int i
= 0; i
< 100; i
++)
237 QueryServiceStatus(service
, &serviceStatus
);
238 if (serviceStatus
.dwCurrentState
== SERVICE_STOPPED
)
256 void installService()
258 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE
);
260 if (serviceControlManager
)
262 SC_HANDLE service
= OpenService(serviceControlManager
,
263 serviceName
, SERVICE_QUERY_STATUS
);
266 printf("Service Already Exists..\n");
267 StartService(service
,0,NULL
);
268 CloseServiceHandle(service
);
272 TCHAR path
[ _MAX_PATH
+ 1 ];
273 if (GetModuleFileName(0, path
, sizeof(path
) / sizeof(path
[0])) > 0)
275 SC_HANDLE service
= CreateService(serviceControlManager
,
276 serviceName
, displayName
,
277 SERVICE_ALL_ACCESS
, SERVICE_WIN32_OWN_PROCESS
,
278 SERVICE_AUTO_START
, SERVICE_ERROR_IGNORE
, path
,
282 printf("Successfully installed.. !\n");
283 StartService(service
,0,NULL
);
284 CloseServiceHandle(service
);
287 printf("Installation Failed..\n");
290 CloseServiceHandle(serviceControlManager
);
296 void uninstallService()
298 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
300 if (serviceControlManager
)
302 SC_HANDLE service
= OpenService(serviceControlManager
,
303 serviceName
, SERVICE_QUERY_STATUS
| SERVICE_STOP
| DELETE
);
306 if (stopService(service
))
308 DeleteService(service
);
309 printf("Successfully Removed !\n");
312 printf("Failed to Stop Service..\n");
314 CloseServiceHandle(service
);
317 CloseServiceHandle(serviceControlManager
);
323 void printWindowsError()
325 MYDWORD dw
= GetLastError();
332 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
333 FORMAT_MESSAGE_FROM_SYSTEM
|
334 FORMAT_MESSAGE_IGNORE_INSERTS
,
337 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
341 printf("Error: %s\nPress Enter..\n", (LPTSTR
)lpMsgBuf
);
346 int main(int argc
, TCHAR
* argv
[])
349 osvi
.dwOSVersionInfoSize
= sizeof(osvi
);
350 bool result
= GetVersionEx(&osvi
);
352 if (result
&& osvi
.dwPlatformId
>= VER_PLATFORM_WIN32_NT
)
354 if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-i")) == 0)
356 else if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-u")) == 0)
358 else if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-v")) == 0)
360 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
361 bool serviceStopped
= true;
363 if (serviceControlManager
)
365 SC_HANDLE service
= OpenService(serviceControlManager
,
366 serviceName
, SERVICE_QUERY_STATUS
| SERVICE_STOP
);
369 serviceStopped
= stopService(service
);
370 CloseServiceHandle(service
);
372 CloseServiceHandle(serviceControlManager
);
380 printf("Failed to Stop Service\n");
385 else if (argc
== 1 || lstrcmpi(argv
[1], TEXT("-v")) == 0)
388 printf("This option is not available on Windows95/98/ME\n");
397 if (_beginthread(init
, 0, 0) == 0)
401 sprintf(logBuff
, "Thread Creation Failed");
413 printf("\naccepting requests..\n");
417 network
.busy
= false;
419 //printf("Active=%u Total=%u\n",activeThreads, totalThreads);
421 if (!network
.tftpConn
[0].ready
|| !network
.ready
)
429 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].ready
; i
++)
430 FD_SET(network
.tftpConn
[i
].sock
, &readfds
);
432 fdsReady
= select(network
.maxFD
, &readfds
, NULL
, NULL
, &tv
);
437 //errno = WSAGetLastError();
440 // printf("%d\n", errno);
442 for (int i
= 0; fdsReady
> 0 && i
< MAX_SERVERS
&& network
.tftpConn
[i
].ready
; i
++)
448 if (FD_ISSET(network
.tftpConn
[i
].sock
, &readfds
))
450 //printf("%d Requests Waiting\n", fdsReady);
452 WaitForSingleObject(sEvent
, INFINITE
);
456 if (!totalThreads
|| activeThreads
>= totalThreads
)
459 processRequest
, // thread function
460 0, // default security attributes
461 NULL
); // argument to thread function
465 //printf("thread signalled=%u\n",SetEvent(tEvent));
467 WaitForSingleObject(sEvent
, INFINITE
);
483 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].loaded
; i
++)
484 if (network
.tftpConn
[i
].ready
)
485 closesocket(network
.tftpConn
[i
].sock
);
488 void processRequest(void *lpParam
)
490 //printf("New Thread %u\n",GetCurrentThreadId());
494 WaitForSingleObject(cEvent
, INFINITE
);
500 WaitForSingleObject(tEvent
, INFINITE
);
501 //printf("In Thread %u\n",GetCurrentThreadId());
503 WaitForSingleObject(cEvent
, INFINITE
);
507 if (currentServer
>= MAX_SERVERS
|| !network
.tftpConn
[currentServer
].port
)
510 req
.attempt
= UCHAR_MAX
;
514 memset(&req
, 0, sizeof(request
));
515 req
.sock
= INVALID_SOCKET
;
517 req
.clientsize
= sizeof(req
.client
);
518 req
.sockInd
= currentServer
;
519 currentServer
= UCHAR_MAX
;
520 req
.knock
= network
.tftpConn
[req
.sockInd
].sock
;
522 if (req
.knock
== INVALID_SOCKET
)
525 req
.attempt
= UCHAR_MAX
;
530 req
.bytesRecd
= recvfrom(req
.knock
, (char*)&req
.mesin
, sizeof(message
), 0, (sockaddr
*)&req
.client
, &req
.clientsize
);
531 errno
= WSAGetLastError();
533 //printf("socket Signalled=%u\n",SetEvent(sEvent));
536 if (!errno
&& req
.bytesRecd
> 0)
538 if (cfig
.hostRanges
[0].rangeStart
)
540 MYDWORD iip
= ntohl(req
.client
.sin_addr
.s_addr
);
541 bool allowed
= false;
544 for (int j
= 0; j
< _countof(cfig
.hostRanges
) && cfig
.hostRanges
[j
].rangeStart
; j
++)
546 for (int j
= 0; j
<= 32 && cfig
.hostRanges
[j
].rangeStart
; j
++)
549 if (iip
>= cfig
.hostRanges
[j
].rangeStart
&& iip
<= cfig
.hostRanges
[j
].rangeEnd
)
558 req
.serverError
.opcode
= htons(5);
559 req
.serverError
.errorcode
= htons(2);
560 strcpy(req
.serverError
.errormessage
, "Access Denied");
562 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
563 req
.attempt
= UCHAR_MAX
;
568 if ((htons(req
.mesin
.opcode
) == 5))
570 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.clientError
.errorcode
), req
.clientError
.errormessage
);
572 req
.attempt
= UCHAR_MAX
;
575 else if (htons(req
.mesin
.opcode
) != 1 && htons(req
.mesin
.opcode
) != 2)
577 req
.serverError
.opcode
= htons(5);
578 req
.serverError
.errorcode
= htons(5);
579 sprintf(req
.serverError
.errormessage
, "Unknown Transfer Id");
581 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
582 req
.attempt
= UCHAR_MAX
;
588 sprintf(req
.serverError
.errormessage
, "Communication Error");
590 req
.attempt
= UCHAR_MAX
;
595 req
.timeout
= timeout
;
596 req
.expiry
= time(NULL
) + req
.timeout
;
597 bool fetchAck
= false;
599 req
.sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
601 if (req
.sock
== INVALID_SOCKET
)
603 req
.serverError
.opcode
= htons(5);
604 req
.serverError
.errorcode
= htons(0);
605 strcpy(req
.serverError
.errormessage
, "Thread Socket Creation Error");
606 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
608 req
.attempt
= UCHAR_MAX
;
613 service
.sin_family
= AF_INET
;
614 service
.sin_addr
.s_addr
= network
.tftpConn
[req
.sockInd
].server
;
618 for (MYWORD comport
= cfig
.minport
; ; comport
++)
620 service
.sin_port
= htons(comport
);
622 if (comport
> cfig
.maxport
)
624 req
.serverError
.opcode
= htons(5);
625 req
.serverError
.errorcode
= htons(0);
626 strcpy(req
.serverError
.errormessage
, "No port is free");
627 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
629 req
.attempt
= UCHAR_MAX
;
632 else if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
640 service
.sin_port
= 0;
642 if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
644 strcpy(req
.serverError
.errormessage
, "Thread failed to bind");
645 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
647 req
.attempt
= UCHAR_MAX
;
651 if (req
.attempt
>= 3)
654 if (connect(req
.sock
, (sockaddr
*)&req
.client
, req
.clientsize
) == -1)
656 req
.serverError
.opcode
= htons(5);
657 req
.serverError
.errorcode
= htons(0);
658 strcpy(req
.serverError
.errormessage
, "Connect Failed");
659 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
661 req
.attempt
= UCHAR_MAX
;
665 //sprintf(req.serverError.errormessage, "In Temp, Socket");
668 char *inPtr
= req
.mesin
.buffer
;
669 *(inPtr
+ (req
.bytesRecd
- 3)) = 0;
670 req
.filename
= inPtr
;
672 if (!strlen(req
.filename
) || strlen(req
.filename
) > UCHAR_MAX
)
674 req
.serverError
.opcode
= htons(5);
675 req
.serverError
.errorcode
= htons(4);
676 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Filename");
677 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
678 req
.attempt
= UCHAR_MAX
;
683 inPtr
+= strlen(inPtr
) + 1;
686 if (!strlen(req
.mode
) || strlen(req
.mode
) > 25)
688 req
.serverError
.opcode
= htons(5);
689 req
.serverError
.errorcode
= htons(4);
690 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Mode");
691 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
692 req
.attempt
= UCHAR_MAX
;
697 inPtr
+= strlen(inPtr
) + 1;
699 for (MYDWORD i
= 0; i
< strlen(req
.filename
); i
++)
700 if (req
.filename
[i
] == notFileSep
)
701 req
.filename
[i
] = fileSep
;
705 tempbuff
[2] = fileSep
;
708 if (strstr(req
.filename
, tempbuff
))
710 req
.serverError
.opcode
= htons(5);
711 req
.serverError
.errorcode
= htons(2);
712 strcpy(req
.serverError
.errormessage
, "Access violation");
713 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
715 req
.attempt
= UCHAR_MAX
;
719 if (req
.filename
[0] == fileSep
)
722 if (!cfig
.homes
[0].alias
[0])
724 if (strlen(cfig
.homes
[0].target
) + strlen(req
.filename
) >= sizeof(req
.path
))
726 req
.serverError
.opcode
= htons(5);
727 req
.serverError
.errorcode
= htons(4);
728 sprintf(req
.serverError
.errormessage
, "Filename too large");
729 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
731 req
.attempt
= UCHAR_MAX
;
735 strcpy(req
.path
, cfig
.homes
[0].target
);
736 strcat(req
.path
, req
.filename
);
740 char *bname
= strchr(req
.filename
, fileSep
);
749 req
.serverError
.opcode
= htons(5);
750 req
.serverError
.errorcode
= htons(2);
751 sprintf(req
.serverError
.errormessage
, "Missing directory/alias");
752 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
754 req
.attempt
= UCHAR_MAX
;
758 for (int i
= 0; i
< 8; i
++)
760 //printf("%s=%i\n", req.filename, cfig.homes[i].alias[0]);
761 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(req
.filename
, cfig
.homes
[i
].alias
))
763 if (strlen(cfig
.homes
[i
].target
) + strlen(bname
) >= sizeof(req
.path
))
765 req
.serverError
.opcode
= htons(5);
766 req
.serverError
.errorcode
= htons(4);
767 sprintf(req
.serverError
.errormessage
, "Filename too large");
768 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
770 req
.attempt
= UCHAR_MAX
;
774 strcpy(req
.path
, cfig
.homes
[i
].target
);
775 strcat(req
.path
, bname
);
778 else if (i
== 7 || !cfig
.homes
[i
].alias
[0])
780 req
.serverError
.opcode
= htons(5);
781 req
.serverError
.errorcode
= htons(2);
782 sprintf(req
.serverError
.errormessage
, "No such directory/alias %s", req
.filename
);
783 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
785 req
.attempt
= UCHAR_MAX
;
791 if (req
.attempt
>= 3)
794 if (ntohs(req
.mesin
.opcode
) == 1)
798 req
.serverError
.opcode
= htons(5);
799 req
.serverError
.errorcode
= htons(2);
800 strcpy(req
.serverError
.errormessage
, "GET Access Denied");
802 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
803 req
.attempt
= UCHAR_MAX
;
813 if (!strcasecmp(tmp
, "blksize"))
815 tmp
+= strlen(tmp
) + 1;
816 MYDWORD val
= atol(tmp
);
820 else if (val
> blksize
)
827 tmp
+= strlen(tmp
) + 1;
833 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
834 req
.file
= fopen(req
.path
, "rt");
836 req
.file
= fopen(req
.path
, "rb");
838 if (errno
|| !req
.file
)
840 req
.serverError
.opcode
= htons(5);
841 req
.serverError
.errorcode
= htons(1);
842 strcpy(req
.serverError
.errormessage
, "File not found or No Access");
844 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
845 req
.attempt
= UCHAR_MAX
;
851 if (!cfig
.fileWrite
&& !cfig
.fileOverwrite
)
853 req
.serverError
.opcode
= htons(5);
854 req
.serverError
.errorcode
= htons(2);
855 strcpy(req
.serverError
.errormessage
, "PUT Access Denied");
856 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
858 req
.attempt
= UCHAR_MAX
;
862 req
.file
= fopen(req
.path
, "rb");
869 if (!cfig
.fileOverwrite
)
871 req
.serverError
.opcode
= htons(5);
872 req
.serverError
.errorcode
= htons(6);
873 strcpy(req
.serverError
.errormessage
, "File already exists");
874 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
876 req
.attempt
= UCHAR_MAX
;
880 else if (!cfig
.fileWrite
)
882 req
.serverError
.opcode
= htons(5);
883 req
.serverError
.errorcode
= htons(2);
884 strcpy(req
.serverError
.errormessage
, "Create File Access Denied");
885 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
887 req
.attempt
= UCHAR_MAX
;
893 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
894 req
.file
= fopen(req
.path
, "wt");
896 req
.file
= fopen(req
.path
, "wb");
898 if (errno
|| !req
.file
)
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);
905 req
.attempt
= UCHAR_MAX
;
910 setvbuf(req
.file
, NULL
, _IOFBF
, 5 * req
.blksize
);
915 char *outPtr
= req
.mesout
.buffer
;
916 req
.mesout
.opcode
= htons(6);
920 //printf("%s\n", inPtr);
921 if (!strcasecmp(inPtr
, "blksize"))
923 strcpy(outPtr
, inPtr
);
924 outPtr
+= strlen(outPtr
) + 1;
925 inPtr
+= strlen(inPtr
) + 1;
930 else if (val
> blksize
)
934 sprintf(outPtr
, "%u", val
);
935 outPtr
+= strlen(outPtr
) + 1;
937 else if (!strcasecmp(inPtr
, "tsize"))
939 strcpy(outPtr
, inPtr
);
940 outPtr
+= strlen(outPtr
) + 1;
941 inPtr
+= strlen(inPtr
) + 1;
943 if (ntohs(req
.mesin
.opcode
) == 1)
945 if (!fseek(req
.file
, 0, SEEK_END
))
947 if (ftell(req
.file
) >= 0)
949 req
.tsize
= ftell(req
.file
);
950 sprintf(outPtr
, "%u", req
.tsize
);
951 outPtr
+= strlen(outPtr
) + 1;
955 req
.serverError
.opcode
= htons(5);
956 req
.serverError
.errorcode
= htons(2);
957 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
958 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
960 req
.attempt
= UCHAR_MAX
;
966 req
.serverError
.opcode
= htons(5);
967 req
.serverError
.errorcode
= htons(2);
968 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
969 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
971 req
.attempt
= UCHAR_MAX
;
978 sprintf(outPtr
, "%u", req
.tsize
);
979 outPtr
+= strlen(outPtr
) + 1;
982 else if (!strcasecmp(inPtr
, "timeout"))
984 strcpy(outPtr
, inPtr
);
985 outPtr
+= strlen(outPtr
) + 1;
986 inPtr
+= strlen(inPtr
) + 1;
991 else if (val
> UCHAR_MAX
)
995 req
.expiry
= time(NULL
) + req
.timeout
;
996 sprintf(outPtr
, "%u", val
);
997 outPtr
+= strlen(outPtr
) + 1;
1000 inPtr
+= strlen(inPtr
) + 1;
1001 //printf("=%u\n", val);
1004 if (req
.attempt
>= 3)
1008 req
.bytesReady
= (MYDWORD
)outPtr
- (MYDWORD
)&req
.mesout
;
1009 //printf("Bytes Ready=%u\n", req.bytesReady);
1010 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1011 errno
= WSAGetLastError();
1013 else if (htons(req
.mesin
.opcode
) == 2)
1015 req
.acout
.opcode
= htons(4);
1016 req
.acout
.block
= htons(0);
1019 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1020 errno
= WSAGetLastError();
1025 sprintf(req
.serverError
.errormessage
, "Communication Error");
1027 req
.attempt
= UCHAR_MAX
;
1030 else if (ntohs(req
.mesin
.opcode
) == 1)
1033 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1034 req
.pkt
[1] = (packet
*)calloc(1, req
.blksize
+ 4);
1036 if (errno
|| !req
.pkt
[0] || !req
.pkt
[1])
1038 sprintf(req
.serverError
.errormessage
, "Memory Error");
1040 req
.attempt
= UCHAR_MAX
;
1044 long ftellLoc
= ftell(req
.file
);
1048 if (fseek(req
.file
, 0, SEEK_SET
))
1050 req
.serverError
.opcode
= htons(5);
1051 req
.serverError
.errorcode
= htons(2);
1052 strcpy(req
.serverError
.errormessage
, "File Access Error");
1053 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1055 req
.attempt
= UCHAR_MAX
;
1059 else if (ftellLoc
< 0)
1061 req
.serverError
.opcode
= htons(5);
1062 req
.serverError
.errorcode
= htons(2);
1063 strcpy(req
.serverError
.errormessage
, "File Access Error");
1064 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1066 req
.attempt
= UCHAR_MAX
;
1071 req
.pkt
[0]->opcode
= htons(3);
1072 req
.pkt
[0]->block
= htons(1);
1073 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1077 req
.serverError
.opcode
= htons(5);
1078 req
.serverError
.errorcode
= htons(2);
1079 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1080 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1082 req
.attempt
= UCHAR_MAX
;
1086 if (req
.bytesRead
[0] == req
.blksize
)
1088 req
.pkt
[1]->opcode
= htons(3);
1089 req
.pkt
[1]->block
= htons(2);
1090 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1091 if (req
.bytesRead
[1] < req
.blksize
)
1105 req
.serverError
.opcode
= htons(5);
1106 req
.serverError
.errorcode
= htons(2);
1107 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1108 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1110 req
.attempt
= UCHAR_MAX
;
1114 while (req
.attempt
<= 3)
1118 FD_ZERO(&req
.readfds
);
1121 FD_SET(req
.sock
, &req
.readfds
);
1122 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1124 if (FD_ISSET(req
.sock
, &req
.readfds
))
1127 req
.bytesRecd
= recv(req
.sock
, (char*)&req
.mesin
, sizeof(message
), 0);
1128 errno
= WSAGetLastError();
1129 if (req
.bytesRecd
<= 0 || errno
)
1131 sprintf(req
.serverError
.errormessage
, "Communication Error");
1133 req
.attempt
= UCHAR_MAX
;
1136 else if(req
.bytesRecd
>= 4 && ntohs(req
.mesin
.opcode
) == 4)
1138 if (ntohs(req
.acin
.block
) == req
.block
)
1144 else if (req
.expiry
> time(NULL
))
1149 else if (ntohs(req
.mesin
.opcode
) == 5)
1151 sprintf(req
.serverError
.errormessage
, "Client %s:%u, Error Code %i at Client, %s", inet_ntoa(req
.client
.sin_addr
), ntohs(req
.client
.sin_port
), ntohs(req
.clientError
.errorcode
), req
.clientError
.errormessage
);
1153 req
.attempt
= UCHAR_MAX
;
1158 req
.serverError
.opcode
= htons(5);
1159 req
.serverError
.errorcode
= htons(4);
1160 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.mesin
.opcode
));
1161 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1163 req
.attempt
= UCHAR_MAX
;
1167 else if (req
.expiry
> time(NULL
))
1180 if (req
.attempt
>= 3)
1182 req
.serverError
.opcode
= htons(5);
1183 req
.serverError
.errorcode
= htons(0);
1185 if (req
.fblock
&& !req
.block
)
1186 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1188 strcpy(req
.serverError
.errormessage
, "Timeout");
1191 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1192 req
.attempt
= UCHAR_MAX
;
1195 else if (!req
.fblock
)
1198 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1199 errno
= WSAGetLastError();
1202 sprintf(req
.serverError
.errormessage
, "Communication Error");
1204 req
.attempt
= UCHAR_MAX
;
1207 req
.expiry
= time(NULL
) + req
.timeout
;
1209 else if (ntohs(req
.pkt
[0]->block
) == req
.block
)
1212 send(req
.sock
, (const char*)req
.pkt
[0], req
.bytesRead
[0] + 4, 0);
1213 errno
= WSAGetLastError();
1216 sprintf(req
.serverError
.errormessage
, "Communication Error");
1218 req
.attempt
= UCHAR_MAX
;
1221 req
.expiry
= time(NULL
) + req
.timeout
;
1225 req
.tblock
= ntohs(req
.pkt
[1]->block
) + 1;
1226 if (req
.tblock
== req
.block
)
1228 req
.pkt
[1]->block
= htons(++req
.tblock
);
1229 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1233 req
.serverError
.opcode
= htons(5);
1234 req
.serverError
.errorcode
= htons(4);
1235 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1236 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1238 req
.attempt
= UCHAR_MAX
;
1241 else if (req
.bytesRead
[1] < req
.blksize
)
1249 else if (ntohs(req
.pkt
[1]->block
) == req
.block
)
1252 send(req
.sock
, (const char*)req
.pkt
[1], req
.bytesRead
[1] + 4, 0);
1253 errno
= WSAGetLastError();
1256 sprintf(req
.serverError
.errormessage
, "Communication Error");
1258 req
.attempt
= UCHAR_MAX
;
1262 req
.expiry
= time(NULL
) + req
.timeout
;
1266 req
.tblock
= ntohs(req
.pkt
[0]->block
) + 1;
1267 if (req
.tblock
== req
.block
)
1269 req
.pkt
[0]->block
= htons(++req
.tblock
);
1270 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1273 req
.serverError
.opcode
= htons(5);
1274 req
.serverError
.errorcode
= htons(4);
1275 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1276 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1278 req
.attempt
= UCHAR_MAX
;
1281 else if (req
.bytesRead
[0] < req
.blksize
)
1291 sprintf(req
.serverError
.errormessage
, "%u Blocks Served", req
.fblock
- 1);
1293 req
.attempt
= UCHAR_MAX
;
1298 else if (ntohs(req
.mesin
.opcode
) == 2)
1301 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1303 if (errno
|| !req
.pkt
[0])
1305 sprintf(req
.serverError
.errormessage
, "Memory Error");
1307 req
.attempt
= UCHAR_MAX
;
1311 while (req
.attempt
<= 3)
1313 FD_ZERO(&req
.readfds
);
1316 FD_SET(req
.sock
, &req
.readfds
);
1317 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1319 if (FD_ISSET(req
.sock
, &req
.readfds
))
1322 req
.bytesRecd
= recv(req
.sock
, (char*)req
.pkt
[0], req
.blksize
+ 4, 0);
1323 errno
= WSAGetLastError();
1327 sprintf(req
.serverError
.errormessage
, "Communication Error");
1329 req
.attempt
= UCHAR_MAX
;
1336 if (req
.bytesRecd
>= 4)
1338 if (ntohs(req
.pkt
[0]->opcode
) == 3)
1340 req
.tblock
= req
.block
+ 1;
1342 if (ntohs(req
.pkt
[0]->block
) == req
.tblock
)
1344 req
.acout
.opcode
= htons(4);
1345 req
.acout
.block
= req
.pkt
[0]->block
;
1349 req
.expiry
= time(NULL
) + req
.timeout
;
1352 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1353 errno
= WSAGetLastError();
1357 sprintf(req
.serverError
.errormessage
, "Communication Error");
1359 req
.attempt
= UCHAR_MAX
;
1363 if (req
.bytesRecd
> 4)
1366 if (fwrite(&req
.pkt
[0]->buffer
, req
.bytesRecd
- 4, 1, req
.file
) != 1 || errno
)
1368 req
.serverError
.opcode
= htons(5);
1369 req
.serverError
.errorcode
= htons(3);
1370 strcpy(req
.serverError
.errormessage
, "Disk full or allocation exceeded");
1371 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1373 req
.attempt
= UCHAR_MAX
;
1382 if ((MYWORD
)req
.bytesRecd
< req
.blksize
+ 4)
1386 sprintf(req
.serverError
.errormessage
, "%u Blocks Received", req
.fblock
);
1388 req
.attempt
= UCHAR_MAX
;
1392 else if (req
.expiry
> time(NULL
))
1394 else if (req
.attempt
>= 3)
1396 req
.serverError
.opcode
= htons(5);
1397 req
.serverError
.errorcode
= htons(0);
1399 if (req
.fblock
&& !req
.block
)
1400 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1402 strcpy(req
.serverError
.errormessage
, "Timeout");
1405 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1406 req
.attempt
= UCHAR_MAX
;
1411 req
.expiry
= time(NULL
) + req
.timeout
;
1413 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1414 errno
= WSAGetLastError();
1419 sprintf(req
.serverError
.errormessage
, "Communication Error");
1421 req
.attempt
= UCHAR_MAX
;
1426 else if (req
.bytesRecd
> (int)sizeof(message
))
1428 req
.serverError
.opcode
= htons(5);
1429 req
.serverError
.errorcode
= htons(4);
1430 sprintf(req
.serverError
.errormessage
, "Error: Incoming Packet too large");
1431 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1433 req
.attempt
= UCHAR_MAX
;
1436 else if (ntohs(req
.pkt
[0]->opcode
) == 5)
1438 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.pkt
[0]->block
), &req
.pkt
[0]->buffer
);
1440 req
.attempt
= UCHAR_MAX
;
1445 req
.serverError
.opcode
= htons(5);
1446 req
.serverError
.errorcode
= htons(4);
1447 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.pkt
[0]->opcode
));
1448 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1450 req
.attempt
= UCHAR_MAX
;
1454 else if (req
.expiry
> time(NULL
))
1456 else if (req
.attempt
>= 3)
1458 req
.serverError
.opcode
= htons(5);
1459 req
.serverError
.errorcode
= htons(0);
1461 if (req
.fblock
&& !req
.block
)
1462 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1464 strcpy(req
.serverError
.errormessage
, "Timeout");
1467 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1468 req
.attempt
= UCHAR_MAX
;
1473 req
.expiry
= time(NULL
) + req
.timeout
;
1475 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1476 errno
= WSAGetLastError();
1481 sprintf(req
.serverError
.errormessage
, "Communication Error");
1483 req
.attempt
= UCHAR_MAX
;
1490 while (cleanReq(&req
));
1492 WaitForSingleObject(cEvent
, INFINITE
);
1496 //printf("Thread %u Killed\n",GetCurrentThreadId());
1501 bool cleanReq(request
* req
)
1503 //printf("cleaning\n");
1508 if (!(req
->sock
== INVALID_SOCKET
))
1511 closesocket(req
->sock
);
1520 WaitForSingleObject(cEvent
, INFINITE
);
1524 //printf("cleaned\n");
1526 return (totalThreads
<= minThreads
);
1529 bool getSection(const char *sectionName
, char *buffer
, MYBYTE serial
, char *fileName
)
1531 //printf("%s=%s\n",fileName,sectionName);
1533 sprintf(section
, "[%s]", sectionName
);
1535 FILE *f
= fopen(fileName
, "rt");
1541 while (fgets(buff
, 511, f
))
1546 if (strstr(buff
, section
) == buff
)
1549 if (found
== serial
)
1551 //printf("%s=%s\n",fileName,sectionName);
1552 while (fgets(buff
, 511, f
))
1556 if (strstr(buff
, "[") == buff
)
1559 if (((*buff
) >= '0' && (*buff
) <= '9') || ((*buff
) >= 'A' && (*buff
) <= 'Z') || ((*buff
) >= 'a' && (*buff
) <= 'z') || ((*buff
) && strchr("/\\?*", (*buff
))))
1561 buffer
+= sprintf(buffer
, "%s", buff
);
1574 return (found
== serial
);
1577 FILE *openSection(const char *sectionName
, MYBYTE serial
, char *fileName
)
1579 //printf("%s=%s\n",fileName,sectionName);
1581 sprintf(section
, "[%s]", sectionName
);
1583 FILE *f
= fopen(fileName
, "rt");
1589 while (fgets(buff
, 511, f
))
1594 if (strstr(buff
, section
) == buff
)
1598 if (found
== serial
)
1607 char *readSection(char* buff
, FILE *f
)
1609 while (fgets(buff
, 511, f
))
1616 if (((*buff
) >= '0' && (*buff
) <= '9') || ((*buff
) >= 'A' && (*buff
) <= 'Z') || ((*buff
) >= 'a' && (*buff
) <= 'z') || ((*buff
) && strchr("/\\?*", (*buff
))))
1624 char* myGetToken(char* buff
, MYBYTE index
)
1633 buff
+= strlen(buff
) + 1;
1639 MYWORD
myTokenize(char *target
, char *source
, char *sep
, bool whiteSep
)
1647 if (sep
&& sep
[0] && strchr(sep
, (*source
)))
1653 else if (whiteSep
&& (*source
) <= 32)
1680 //printf("%s\n", target);
1685 char* myTrim(char *target
, char *source
)
1687 while ((*source
) && (*source
) <= 32)
1692 for (; i
< 511 && source
[i
]; i
++)
1693 target
[i
] = source
[i
];
1695 target
[i
] = source
[i
];
1698 for (; i
>= 0 && target
[i
] <= 32; i
--)
1705 void mySplit(char *name, char *value, char *source, char splitChar)
1707 char *dp = strchr(source, splitChar);
1711 strncpy(name, source, (dp - source));
1712 name[dp - source] = 0;
1713 strcpy(value, dp + 1);
1715 myTrim(value, value);
1719 strcpy(name, source);
1726 void mySplit(char *name
, char *value
, char *source
, char splitChar
)
1732 for (; source
[i
] && j
<= 510 && source
[i
] != splitChar
; i
++, j
++)
1734 name
[j
] = source
[i
];
1740 for (; k
<= 510 && source
[i
]; i
++, k
++)
1742 value
[k
] = source
[i
];
1750 myTrim(value
, value
);
1751 //printf("%s %s\n", name, value);
1755 char *IP2String(char *target
, MYDWORD ip
)
1759 sprintf(target
, "%u.%u.%u.%u", inaddr
.octate
[0], inaddr
.octate
[1], inaddr
.octate
[2], inaddr
.octate
[3]);
1763 bool isIP(char *string
)
1767 for (; *string
; string
++)
1769 if (*string
== '.' && *(string
+ 1) != '.')
1771 else if (*string
< '0' || *string
> '9')
1781 char *myUpper(char *string
)
1783 char diff
= 'a' - 'A';
1784 MYWORD len
= strlen(string
);
1785 for (int i
= 0; i
< len
; i
++)
1786 if (string
[i
] >= 'a' && string
[i
] <= 'z')
1791 char *myLower(char *string
)
1793 char diff
= 'a' - 'A';
1794 MYWORD len
= strlen(string
);
1795 for (int i
= 0; i
< len
; i
++)
1796 if (string
[i
] >= 'A' && string
[i
] <= 'Z')
1801 void init(void *lpParam
)
1803 memset(&cfig
, 0, sizeof(cfig
));
1805 GetModuleFileName(NULL
, extbuff
, _MAX_PATH
);
1806 char *fileExt
= strrchr(extbuff
, '.');
1808 sprintf(iniFile
, "%s.ini", extbuff
);
1809 sprintf(lnkFile
, "%s.url", extbuff
);
1810 fileExt
= strrchr(extbuff
, '\\');
1813 sprintf(logFile
, "%s\\log\\%s%%Y%%m%%d.log", extbuff
, fileExt
);
1823 printf("%s\n\n", sVersion
);
1825 else if ((f
= openSection("LOGGING", 1, iniFile
)))
1830 while (readSection(raw
, f
))
1832 if (!strcasecmp(raw
, "None"))
1834 else if (!strcasecmp(raw
, "Errors"))
1836 else if (!strcasecmp(raw
, "All"))
1839 sprintf(tempbuff
, "Section [LOGGING], Invalid LogLevel: %s", raw
);
1843 if (!verbatim
&& cfig
.logLevel
&& logFile
[0])
1845 time_t t
= time(NULL
);
1846 tm
*ttm
= localtime(&t
);
1847 loggingDay
= ttm
->tm_yday
;
1848 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
1850 cfig
.logfile
= fopen(extbuff
, "at");
1854 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
1855 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
1856 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
1857 sprintf(logBuff
, "%s Starting..", sVersion
);
1858 logMess(logBuff
, 1);
1861 logMess(tempbuff
, 0);
1865 MYWORD wVersionRequested
= MAKEWORD(1, 1);
1866 WSAStartup(wVersionRequested
, &cfig
.wsaData
);
1868 if (cfig
.wsaData
.wVersion
!= wVersionRequested
)
1870 sprintf(logBuff
, "WSAStartup Error");
1871 logMess(logBuff
, 1);
1874 if ((f
= openSection("HOME", 1, iniFile
)))
1876 while (readSection(raw
, f
))
1878 mySplit(name
, value
, raw
, '=');
1882 if (!cfig
.homes
[0].alias
[0] && cfig
.homes
[0].target
[0])
1884 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", raw
);
1885 logMess(logBuff
, 1);
1887 else if (strchr(name
, notFileSep
) || strchr(name
, fileSep
) || strchr(name
, '>') || strchr(name
, '<') || strchr(name
, '.'))
1889 sprintf(logBuff
, "Section [HOME], invalid chars in alias %s, entry ignored", name
);
1890 logMess(logBuff
, 1);
1892 else if (name
[0] && strlen(name
) < 64 && value
[0])
1894 for (int i
= 0; i
< 8; i
++)
1896 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(name
, cfig
.homes
[i
].alias
))
1898 sprintf(logBuff
, "Section [HOME], Duplicate Entry: %s ignored", raw
);
1899 logMess(logBuff
, 1);
1902 else if (!cfig
.homes
[i
].alias
[0])
1904 strcpy(cfig
.homes
[i
].alias
, name
);
1905 strcpy(cfig
.homes
[i
].target
, value
);
1907 if (cfig
.homes
[i
].target
[strlen(cfig
.homes
[i
].target
) - 1] != fileSep
)
1909 tempbuff
[0] = fileSep
;
1911 strcat(cfig
.homes
[i
].target
, tempbuff
);
1920 sprintf(logBuff
, "Section [HOME], alias %s too large", name
);
1921 logMess(logBuff
, 1);
1924 else if (!cfig
.homes
[0].alias
[0] && !cfig
.homes
[0].target
[0])
1926 strcpy(cfig
.homes
[0].target
, name
);
1928 if (cfig
.homes
[0].target
[strlen(cfig
.homes
[0].target
) - 1] != fileSep
)
1930 tempbuff
[0] = fileSep
;
1932 strcat(cfig
.homes
[0].target
, tempbuff
);
1935 else if (cfig
.homes
[0].alias
[0])
1937 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", raw
);
1938 logMess(logBuff
, 1);
1940 else if (cfig
.homes
[0].target
[0])
1942 sprintf(logBuff
, "Section [HOME], Duplicate Path: %s ignored", raw
);
1943 logMess(logBuff
, 1);
1947 sprintf(logBuff
, "Section [HOME], missing = sign, Invalid Entry: %s ignored", raw
);
1948 logMess(logBuff
, 1);
1953 if (!cfig
.homes
[0].target
[0])
1955 GetModuleFileName(NULL
, cfig
.homes
[0].target
, UCHAR_MAX
);
1956 char *iniFileExt
= strrchr(cfig
.homes
[0].target
, fileSep
);
1957 *(++iniFileExt
) = 0;
1960 cfig
.fileRead
= true;
1962 if ((f
= openSection("TFTP-OPTIONS", 1, iniFile
)))
1964 while (readSection(raw
, f
))
1966 mySplit(name
, value
, raw
, '=');
1970 if (!strcasecmp(name
, "blksize"))
1972 MYDWORD tblksize
= atol(value
);
1976 else if (tblksize
> USHRT_MAX
- 32)
1977 blksize
= USHRT_MAX
- 32;
1981 else if (!strcasecmp(name
, "threadpoolsize"))
1983 minThreads
= atol(value
);
1986 else if (minThreads
> 100)
1989 else if (!strcasecmp(name
, "timeout"))
1991 timeout
= atol(value
);
1994 else if (timeout
> UCHAR_MAX
)
1995 timeout
= UCHAR_MAX
;
1997 else if (!strcasecmp(name
, "Read"))
1999 if (strchr("Yy", *value
))
2000 cfig
.fileRead
= true;
2002 cfig
.fileRead
= false;
2004 else if (!strcasecmp(name
, "Write"))
2006 if (strchr("Yy", *value
))
2007 cfig
.fileWrite
= true;
2009 cfig
.fileWrite
= false;
2011 else if (!strcasecmp(name
, "Overwrite"))
2013 if (strchr("Yy", *value
))
2014 cfig
.fileOverwrite
= true;
2016 cfig
.fileOverwrite
= false;
2018 else if (!strcasecmp(name
, "port-range"))
2020 char *ptr
= strchr(value
, '-');
2024 cfig
.minport
= atol(value
);
2025 cfig
.maxport
= atol(++ptr
);
2027 if (cfig
.minport
< 1024 || cfig
.minport
>= USHRT_MAX
|| cfig
.maxport
< 1024 || cfig
.maxport
>= USHRT_MAX
|| cfig
.minport
> cfig
.maxport
)
2032 sprintf(logBuff
, "Invalid port range %s", value
);
2033 logMess(logBuff
, 1);
2038 sprintf(logBuff
, "Invalid port range %s", value
);
2039 logMess(logBuff
, 1);
2044 sprintf(logBuff
, "Warning: unknown option %s, ignored", name
);
2045 logMess(logBuff
, 1);
2051 if ((f
= openSection("ALLOWED-CLIENTS", 1, iniFile
)))
2055 while (readSection(raw
, f
))
2058 if (i
< _countof(cfig
.hostRanges
))
2065 mySplit(name
, value
, raw
, '-');
2066 rs
= htonl(my_inet_addr(name
));
2069 re
= htonl(my_inet_addr(value
));
2073 if (rs
&& rs
!= INADDR_NONE
&& re
&& re
!= INADDR_NONE
&& rs
<= re
)
2075 cfig
.hostRanges
[i
].rangeStart
= rs
;
2076 cfig
.hostRanges
[i
].rangeEnd
= re
;
2081 sprintf(logBuff
, "Section [ALLOWED-CLIENTS] Invalid entry %s in ini file, ignored", raw
);
2082 logMess(logBuff
, 1);
2090 printf("starting TFTP...\n");
2094 sprintf(logBuff
, "starting TFTP service");
2095 logMess(logBuff
, 1);
2098 for (int i
= 0; i
< MAX_SERVERS
; i
++)
2099 if (cfig
.homes
[i
].target
[0])
2101 sprintf(logBuff
, "alias /%s is mapped to %s", cfig
.homes
[i
].alias
, cfig
.homes
[i
].target
);
2102 logMess(logBuff
, 1);
2105 if (cfig
.hostRanges
[0].rangeStart
)
2110 for (int i
= 0; i
< _countof(cfig
.hostRanges
) && cfig
.hostRanges
[i
].rangeStart
; i
++)
2112 for (MYWORD i
= 0; i
<= sizeof(cfig
.hostRanges
) && cfig
.hostRanges
[i
].rangeStart
; i
++)
2115 sprintf(logBuff
, "%s", "permitted clients: ");
2116 sprintf(temp
, "%s-", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeStart
)));
2117 strcat(logBuff
, temp
);
2118 sprintf(temp
, "%s", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeEnd
)));
2119 strcat(logBuff
, temp
);
2120 logMess(logBuff
, 1);
2125 sprintf(logBuff
, "%s", "permitted clients: all");
2126 logMess(logBuff
, 1);
2131 sprintf(logBuff
, "server port range: %u-%u", cfig
.minport
, cfig
.maxport
);
2132 logMess(logBuff
, 1);
2136 sprintf(logBuff
, "server port range: all");
2137 logMess(logBuff
, 1);
2140 sprintf(logBuff
, "max blksize: %u", blksize
);
2141 logMess(logBuff
, 1);
2142 sprintf(logBuff
, "default blksize: %u", 512);
2143 logMess(logBuff
, 1);
2144 sprintf(logBuff
, "default timeout: %u", timeout
);
2145 logMess(logBuff
, 1);
2146 sprintf(logBuff
, "file read allowed: %s", cfig
.fileRead
? "Yes" : "No");
2147 logMess(logBuff
, 1);
2148 sprintf(logBuff
, "file create allowed: %s", cfig
.fileWrite
? "Yes" : "No");
2149 logMess(logBuff
, 1);
2150 sprintf(logBuff
, "file overwrite allowed: %s", cfig
.fileOverwrite
? "Yes" : "No");
2151 logMess(logBuff
, 1);
2155 sprintf(logBuff
, "logging: %s", cfig
.logLevel
> 1 ? "all" : "errors");
2156 logMess(logBuff
, 1);
2159 lEvent
= CreateEvent(
2160 NULL
, // default security descriptor
2161 FALSE
, // ManualReset
2163 TEXT("AchalTFTServerLogEvent")); // object name
2167 printf("CreateEvent error: %lu\n", GetLastError());
2170 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2172 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2173 logMess(logBuff
, 0);
2177 tEvent
= CreateEvent(
2178 NULL
, // default security descriptor
2179 FALSE
, // ManualReset
2181 TEXT("AchalTFTServerThreadEvent")); // object name
2185 printf("CreateEvent error: %lu\n", GetLastError());
2188 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2190 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2191 logMess(logBuff
, 0);
2195 sEvent
= CreateEvent(
2196 NULL
, // default security descriptor
2197 FALSE
, // ManualReset
2199 TEXT("AchalTFTServerSocketEvent")); // object name
2203 printf("CreateEvent error: %lu\n", GetLastError());
2206 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2208 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2209 logMess(logBuff
, 0);
2213 cEvent
= CreateEvent(
2214 NULL
, // default security descriptor
2215 FALSE
, // ManualReset
2217 TEXT("AchalTFTServerCountEvent")); // object name
2221 printf("CreateEvent error: %lu\n", GetLastError());
2224 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2226 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2227 logMess(logBuff
, 0);
2233 for (int i
= 0; i
< minThreads
; i
++)
2236 processRequest
, // thread function
2237 0, // default security attributes
2238 NULL
); // argument to thread function
2241 sprintf(logBuff
, "thread pool size: %u", minThreads
);
2242 logMess(logBuff
, 1);
2245 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].port
; i
++)
2247 sprintf(logBuff
, "listening on: %s:%i", IP2String(tempbuff
, network
.tftpConn
[i
].server
), network
.tftpConn
[i
].port
);
2248 logMess(logBuff
, 1);
2253 memset(&newNetwork
, 0, sizeof(data1
));
2255 bool bindfailed
= false;
2257 if ((f
= openSection("LISTEN-ON", 1, iniFile
)))
2261 while (readSection(raw
, f
))
2265 cfig
.ifspecified
= true;
2266 mySplit(name
, value
, raw
, ':');
2275 MYDWORD addr
= my_inet_addr(name
);
2279 newNetwork
.listenServers
[0] = 0;
2280 newNetwork
.listenPorts
[0] = port
;
2284 else if (!findServer(newNetwork
.listenServers
, addr
))
2286 newNetwork
.listenServers
[i
] = addr
;
2287 newNetwork
.listenPorts
[i
] = port
;
2293 sprintf(logBuff
, "Warning: Section [LISTEN-ON], Invalid Interface Address %s, ignored", raw
);
2294 logMess(logBuff
, 1);
2300 if (!cfig
.ifspecified
)
2302 sprintf(logBuff
, "detecting Interfaces..");
2303 logMess(logBuff
, 1);
2304 getInterfaces(&newNetwork
);
2306 for (MYBYTE n
= 0; n
< MAX_SERVERS
&& newNetwork
.staticServers
[n
]; n
++)
2308 newNetwork
.listenServers
[n
] = newNetwork
.staticServers
[n
];
2309 newNetwork
.listenPorts
[n
] = 69;
2315 for (int j
= 0; j
< MAX_SERVERS
&& newNetwork
.listenPorts
[j
]; j
++)
2319 for (; k
< MAX_SERVERS
&& network
.tftpConn
[k
].loaded
; k
++)
2321 if (network
.tftpConn
[k
].ready
&& network
.tftpConn
[k
].server
== newNetwork
.listenServers
[j
] && network
.tftpConn
[k
].port
== newNetwork
.listenPorts
[j
])
2325 if (network
.tftpConn
[k
].ready
&& network
.tftpConn
[k
].server
== newNetwork
.listenServers
[j
] && network
.tftpConn
[k
].port
== newNetwork
.listenPorts
[j
])
2327 memcpy(&(newNetwork
.tftpConn
[i
]), &(network
.tftpConn
[k
]), sizeof(tftpConnType
));
2329 if (newNetwork
.maxFD
< newNetwork
.tftpConn
[i
].sock
)
2330 newNetwork
.maxFD
= newNetwork
.tftpConn
[i
].sock
;
2332 network
.tftpConn
[k
].ready
= false;
2333 //printf("%d, %s found\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2339 newNetwork
.tftpConn
[i
].sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
2341 if (newNetwork
.tftpConn
[i
].sock
== INVALID_SOCKET
)
2344 sprintf(logBuff
, "Failed to Create Socket");
2345 logMess(logBuff
, 1);
2349 //printf("Socket %u\n", newNetwork.tftpConn[i].sock);
2352 newNetwork
.tftpConn
[i
].addr
.sin_family
= AF_INET
;
2353 newNetwork
.tftpConn
[i
].addr
.sin_addr
.s_addr
= newNetwork
.listenServers
[j
];
2354 newNetwork
.tftpConn
[i
].addr
.sin_port
= htons(newNetwork
.listenPorts
[j
]);
2355 int nRet
= bind(newNetwork
.tftpConn
[i
].sock
, (sockaddr
*)&newNetwork
.tftpConn
[i
].addr
, sizeof(struct sockaddr_in
));
2357 if (nRet
== SOCKET_ERROR
|| errno
)
2360 closesocket(newNetwork
.tftpConn
[i
].sock
);
2361 sprintf(logBuff
, "%s Port %i bind failed", IP2String(tempbuff
, newNetwork
.listenServers
[j
]), newNetwork
.listenPorts
[j
]);
2362 logMess(logBuff
, 1);
2366 newNetwork
.tftpConn
[i
].loaded
= true;
2367 newNetwork
.tftpConn
[i
].ready
= true;
2368 newNetwork
.tftpConn
[i
].server
= newNetwork
.listenServers
[j
];
2369 newNetwork
.tftpConn
[i
].port
= newNetwork
.listenPorts
[j
];
2371 //printf("%d, %s created\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2373 if (newNetwork
.maxFD
< newNetwork
.tftpConn
[i
].sock
)
2374 newNetwork
.maxFD
= newNetwork
.tftpConn
[i
].sock
;
2376 if (!newNetwork
.listenServers
[j
])
2384 cfig
.failureCount
++;
2386 cfig
.failureCount
= 0;
2389 memcpy(&network
, &newNetwork
, sizeof(data1
));
2391 //printf("%i %i %i\n", network.tftpConn[0].ready, network.dnsUdpConn[0].ready, network.dnsTcpConn[0].ready);
2393 if (!network
.tftpConn
[0].ready
)
2395 sprintf(logBuff
, "No Static Interface ready, Waiting...");
2396 logMess(logBuff
, 1);
2400 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].loaded
; i
++)
2402 sprintf(logBuff
, "Listening On: %s:%d", IP2String(tempbuff
, network
.tftpConn
[i
].server
), network
.tftpConn
[i
].port
);
2403 logMess(logBuff
, 1);
2406 network
.ready
= true;
2408 } while (detectChange());
2410 //printf("Exiting Init\n");
2418 if (!cfig
.failureCount
)
2420 if (cfig
.ifspecified
)
2424 MYDWORD eventWait
= UINT_MAX
;
2426 if (cfig
.failureCount
)
2427 eventWait
= 10000 * pow(2, cfig
.failureCount
);
2432 overlap
.hEvent
= WSACreateEvent();
2434 ret
= NotifyAddrChange(&hand
, &overlap
);
2436 if (ret
!= NO_ERROR
)
2438 if (WSAGetLastError() != WSA_IO_PENDING
)
2440 printf("NotifyAddrChange error...%d\n", WSAGetLastError());
2445 if ( WaitForSingleObject(overlap
.hEvent
, eventWait
) == WAIT_OBJECT_0
)
2446 WSACloseEvent(overlap
.hEvent
);
2448 network
.ready
= false;
2450 while (network
.busy
)
2453 if (cfig
.failureCount
)
2455 sprintf(logBuff
, "Retrying failed Listening Interfaces..");
2456 logMess(logBuff
, 1);
2460 sprintf(logBuff
, "Network changed, re-detecting Interfaces..");
2461 logMess(logBuff
, 1);
2468 void getInterfaces(data1 *network)
2470 memset(network, 0, sizeof(data1));
2472 SOCKET sd = WSASocket(PF_INET, SOCK_DGRAM, 0, 0, 0, 0);
2474 if (sd == INVALID_SOCKET)
2477 INTERFACE_INFO InterfaceList[MAX_SERVERS];
2478 unsigned long nBytesReturned;
2480 if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
2481 sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
2484 int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
2486 for (int i = 0; i < nNumInterfaces; ++i)
2488 sockaddr_in *pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress);
2489 u_long nFlags = InterfaceList[i].iiFlags;
2491 if (!(nFlags & IFF_POINTTOPOINT))
2493 //printf("%s\n", IP2String(tempbuff, pAddress->sin_addr.S_un.S_addr));
2494 addServer(network->staticServers, pAddress->sin_addr.s_addr);
2503 void getInterfaces(data1
*network
)
2505 memset(network
, 0, sizeof(data1
));
2507 SOCKET sd
= WSASocket(PF_INET
, SOCK_DGRAM
, 0, 0, 0, 0);
2509 if (sd
== INVALID_SOCKET
)
2512 INTERFACE_INFO InterfaceList
[MAX_SERVERS
];
2513 unsigned long nBytesReturned
;
2515 if (WSAIoctl(sd
, SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
,
2516 sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
2519 int nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
2521 for (int i
= 0; i
< nNumInterfaces
; ++i
)
2523 sockaddr_in
*pAddress
= (sockaddr_in
*)&(InterfaceList
[i
].iiAddress
);
2524 u_long nFlags
= InterfaceList
[i
].iiFlags
;
2526 if (pAddress
->sin_addr
.s_addr
)
2528 addServer(network
->allServers
, pAddress
->sin_addr
.s_addr
);
2530 if (!(nFlags
& IFF_POINTTOPOINT
) && (nFlags
& IFF_UP
))
2532 addServer(network
->staticServers
, pAddress
->sin_addr
.s_addr
);
2541 bool addServer(MYDWORD
*array
, MYDWORD ip
)
2543 for (MYBYTE i
= 0; i
< MAX_SERVERS
; i
++)
2545 if (!ip
|| array
[i
] == ip
)
2556 MYDWORD
*findServer(MYDWORD
*array
, MYDWORD ip
)
2560 for (MYBYTE i
= 0; i
< MAX_SERVERS
&& array
[i
]; i
++)
2569 void logMess(char *logBuff
, MYBYTE logLevel
)
2571 WaitForSingleObject(lEvent
, INFINITE
);
2574 printf("%s\n", logBuff
);
2575 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2577 time_t t
= time(NULL
);
2578 tm
*ttm
= localtime(&t
);
2580 if (ttm
->tm_yday
!= loggingDay
)
2582 loggingDay
= ttm
->tm_yday
;
2583 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
2584 fprintf(cfig
.logfile
, "Logging Continued on file %s\n", extbuff
);
2585 fclose(cfig
.logfile
);
2586 cfig
.logfile
= fopen(extbuff
, "at");
2590 fprintf(cfig
.logfile
, "%s\n\n", sVersion
);
2591 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
2592 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
2593 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
2599 strftime(extbuff
, sizeof(extbuff
), "%d-%b-%y %X", ttm
);
2600 fprintf(cfig
.logfile
, "[%s] %s\n", extbuff
, logBuff
);
2601 fflush(cfig
.logfile
);
2606 void logMess(request
*req
, MYBYTE logLevel
)
2608 WaitForSingleObject(lEvent
, INFINITE
);
2614 if (!req
->serverError
.errormessage
[0])
2615 sprintf(req
->serverError
.errormessage
, strerror(errno
));
2618 printf("Client %s:%u %s, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->path
, req
->serverError
.errormessage
);
2620 printf("Client %s:%u, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2622 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2624 time_t t
= time(NULL
);
2625 tm
*ttm
= localtime(&t
);
2627 if (ttm
->tm_yday
!= loggingDay
)
2629 loggingDay
= ttm
->tm_yday
;
2630 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
2631 fprintf(cfig
.logfile
, "Logging Continued on file %s\n", extbuff
);
2632 fclose(cfig
.logfile
);
2633 cfig
.logfile
= fopen(extbuff
, "at");
2637 fprintf(cfig
.logfile
, "%s\n\n", sVersion
);
2638 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
2639 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
2640 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
2646 strftime(extbuff
, sizeof(extbuff
), "%d-%b-%y %X", ttm
);
2649 fprintf(cfig
.logfile
, "[%s] Client %s:%u %s, %s\n", extbuff
, IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->path
, req
->serverError
.errormessage
);
2651 fprintf(cfig
.logfile
, "[%s] Client %s:%u, %s\n", extbuff
, IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2653 fflush(cfig
.logfile
);