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 (MYWORD 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
;
759 for (int i
= 0; i
< MAX_SERVERS
; i
++)
761 for (int i
= 0; i
< 8; i
++)
764 //printf("%s=%i\n", req.filename, cfig.homes[i].alias[0]);
765 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(req
.filename
, cfig
.homes
[i
].alias
))
767 if (strlen(cfig
.homes
[i
].target
) + strlen(bname
) >= sizeof(req
.path
))
769 req
.serverError
.opcode
= htons(5);
770 req
.serverError
.errorcode
= htons(4);
771 sprintf(req
.serverError
.errormessage
, "Filename too large");
772 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
774 req
.attempt
= UCHAR_MAX
;
778 strcpy(req
.path
, cfig
.homes
[i
].target
);
779 strcat(req
.path
, bname
);
782 else if (i
== 7 || !cfig
.homes
[i
].alias
[0])
784 req
.serverError
.opcode
= htons(5);
785 req
.serverError
.errorcode
= htons(2);
786 sprintf(req
.serverError
.errormessage
, "No such directory/alias %s", req
.filename
);
787 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
789 req
.attempt
= UCHAR_MAX
;
795 if (req
.attempt
>= 3)
798 if (ntohs(req
.mesin
.opcode
) == 1)
802 req
.serverError
.opcode
= htons(5);
803 req
.serverError
.errorcode
= htons(2);
804 strcpy(req
.serverError
.errormessage
, "GET Access Denied");
806 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
807 req
.attempt
= UCHAR_MAX
;
817 if (!strcasecmp(tmp
, "blksize"))
819 tmp
+= strlen(tmp
) + 1;
820 MYDWORD val
= atol(tmp
);
824 else if (val
> blksize
)
831 tmp
+= strlen(tmp
) + 1;
837 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
838 req
.file
= fopen(req
.path
, "rt");
840 req
.file
= fopen(req
.path
, "rb");
842 if (errno
|| !req
.file
)
844 req
.serverError
.opcode
= htons(5);
845 req
.serverError
.errorcode
= htons(1);
846 strcpy(req
.serverError
.errormessage
, "File not found or No Access");
848 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
849 req
.attempt
= UCHAR_MAX
;
855 if (!cfig
.fileWrite
&& !cfig
.fileOverwrite
)
857 req
.serverError
.opcode
= htons(5);
858 req
.serverError
.errorcode
= htons(2);
859 strcpy(req
.serverError
.errormessage
, "PUT Access Denied");
860 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
862 req
.attempt
= UCHAR_MAX
;
866 req
.file
= fopen(req
.path
, "rb");
873 if (!cfig
.fileOverwrite
)
875 req
.serverError
.opcode
= htons(5);
876 req
.serverError
.errorcode
= htons(6);
877 strcpy(req
.serverError
.errormessage
, "File already exists");
878 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
880 req
.attempt
= UCHAR_MAX
;
884 else if (!cfig
.fileWrite
)
886 req
.serverError
.opcode
= htons(5);
887 req
.serverError
.errorcode
= htons(2);
888 strcpy(req
.serverError
.errormessage
, "Create File Access Denied");
889 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
891 req
.attempt
= UCHAR_MAX
;
897 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
898 req
.file
= fopen(req
.path
, "wt");
900 req
.file
= fopen(req
.path
, "wb");
902 if (errno
|| !req
.file
)
904 req
.serverError
.opcode
= htons(5);
905 req
.serverError
.errorcode
= htons(2);
906 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
907 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
909 req
.attempt
= UCHAR_MAX
;
914 setvbuf(req
.file
, NULL
, _IOFBF
, 5 * req
.blksize
);
919 char *outPtr
= req
.mesout
.buffer
;
920 req
.mesout
.opcode
= htons(6);
924 //printf("%s\n", inPtr);
925 if (!strcasecmp(inPtr
, "blksize"))
927 strcpy(outPtr
, inPtr
);
928 outPtr
+= strlen(outPtr
) + 1;
929 inPtr
+= strlen(inPtr
) + 1;
934 else if (val
> blksize
)
938 sprintf(outPtr
, "%u", val
);
939 outPtr
+= strlen(outPtr
) + 1;
941 else if (!strcasecmp(inPtr
, "tsize"))
943 strcpy(outPtr
, inPtr
);
944 outPtr
+= strlen(outPtr
) + 1;
945 inPtr
+= strlen(inPtr
) + 1;
947 if (ntohs(req
.mesin
.opcode
) == 1)
949 if (!fseek(req
.file
, 0, SEEK_END
))
951 if (ftell(req
.file
) >= 0)
953 req
.tsize
= ftell(req
.file
);
954 sprintf(outPtr
, "%u", req
.tsize
);
955 outPtr
+= strlen(outPtr
) + 1;
959 req
.serverError
.opcode
= htons(5);
960 req
.serverError
.errorcode
= htons(2);
961 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
962 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
964 req
.attempt
= UCHAR_MAX
;
970 req
.serverError
.opcode
= htons(5);
971 req
.serverError
.errorcode
= htons(2);
972 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
973 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
975 req
.attempt
= UCHAR_MAX
;
982 sprintf(outPtr
, "%u", req
.tsize
);
983 outPtr
+= strlen(outPtr
) + 1;
986 else if (!strcasecmp(inPtr
, "timeout"))
988 strcpy(outPtr
, inPtr
);
989 outPtr
+= strlen(outPtr
) + 1;
990 inPtr
+= strlen(inPtr
) + 1;
995 else if (val
> UCHAR_MAX
)
999 req
.expiry
= time(NULL
) + req
.timeout
;
1000 sprintf(outPtr
, "%u", val
);
1001 outPtr
+= strlen(outPtr
) + 1;
1004 inPtr
+= strlen(inPtr
) + 1;
1005 //printf("=%u\n", val);
1008 if (req
.attempt
>= 3)
1012 req
.bytesReady
= (const char*)outPtr
- (const char*)&req
.mesout
;
1013 //printf("Bytes Ready=%u\n", req.bytesReady);
1014 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1015 errno
= WSAGetLastError();
1017 else if (htons(req
.mesin
.opcode
) == 2)
1019 req
.acout
.opcode
= htons(4);
1020 req
.acout
.block
= htons(0);
1023 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1024 errno
= WSAGetLastError();
1029 sprintf(req
.serverError
.errormessage
, "Communication Error");
1031 req
.attempt
= UCHAR_MAX
;
1034 else if (ntohs(req
.mesin
.opcode
) == 1)
1037 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1038 req
.pkt
[1] = (packet
*)calloc(1, req
.blksize
+ 4);
1040 if (errno
|| !req
.pkt
[0] || !req
.pkt
[1])
1042 sprintf(req
.serverError
.errormessage
, "Memory Error");
1044 req
.attempt
= UCHAR_MAX
;
1048 long ftellLoc
= ftell(req
.file
);
1052 if (fseek(req
.file
, 0, SEEK_SET
))
1054 req
.serverError
.opcode
= htons(5);
1055 req
.serverError
.errorcode
= htons(2);
1056 strcpy(req
.serverError
.errormessage
, "File Access Error");
1057 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1059 req
.attempt
= UCHAR_MAX
;
1063 else if (ftellLoc
< 0)
1065 req
.serverError
.opcode
= htons(5);
1066 req
.serverError
.errorcode
= htons(2);
1067 strcpy(req
.serverError
.errormessage
, "File Access Error");
1068 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1070 req
.attempt
= UCHAR_MAX
;
1075 req
.pkt
[0]->opcode
= htons(3);
1076 req
.pkt
[0]->block
= htons(1);
1077 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1081 req
.serverError
.opcode
= htons(5);
1082 req
.serverError
.errorcode
= htons(2);
1083 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1084 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1086 req
.attempt
= UCHAR_MAX
;
1090 if (req
.bytesRead
[0] == req
.blksize
)
1092 req
.pkt
[1]->opcode
= htons(3);
1093 req
.pkt
[1]->block
= htons(2);
1094 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1095 if (req
.bytesRead
[1] < req
.blksize
)
1109 req
.serverError
.opcode
= htons(5);
1110 req
.serverError
.errorcode
= htons(2);
1111 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1112 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1114 req
.attempt
= UCHAR_MAX
;
1118 while (req
.attempt
<= 3)
1122 FD_ZERO(&req
.readfds
);
1125 FD_SET(req
.sock
, &req
.readfds
);
1126 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1128 if (FD_ISSET(req
.sock
, &req
.readfds
))
1131 req
.bytesRecd
= recv(req
.sock
, (char*)&req
.mesin
, sizeof(message
), 0);
1132 errno
= WSAGetLastError();
1133 if (req
.bytesRecd
<= 0 || errno
)
1135 sprintf(req
.serverError
.errormessage
, "Communication Error");
1137 req
.attempt
= UCHAR_MAX
;
1140 else if(req
.bytesRecd
>= 4 && ntohs(req
.mesin
.opcode
) == 4)
1142 if (ntohs(req
.acin
.block
) == req
.block
)
1148 else if (req
.expiry
> time(NULL
))
1153 else if (ntohs(req
.mesin
.opcode
) == 5)
1155 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
);
1157 req
.attempt
= UCHAR_MAX
;
1162 req
.serverError
.opcode
= htons(5);
1163 req
.serverError
.errorcode
= htons(4);
1164 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.mesin
.opcode
));
1165 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1167 req
.attempt
= UCHAR_MAX
;
1171 else if (req
.expiry
> time(NULL
))
1184 if (req
.attempt
>= 3)
1186 req
.serverError
.opcode
= htons(5);
1187 req
.serverError
.errorcode
= htons(0);
1189 if (req
.fblock
&& !req
.block
)
1190 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1192 strcpy(req
.serverError
.errormessage
, "Timeout");
1195 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1196 req
.attempt
= UCHAR_MAX
;
1199 else if (!req
.fblock
)
1202 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1203 errno
= WSAGetLastError();
1206 sprintf(req
.serverError
.errormessage
, "Communication Error");
1208 req
.attempt
= UCHAR_MAX
;
1211 req
.expiry
= time(NULL
) + req
.timeout
;
1213 else if (ntohs(req
.pkt
[0]->block
) == req
.block
)
1216 send(req
.sock
, (const char*)req
.pkt
[0], req
.bytesRead
[0] + 4, 0);
1217 errno
= WSAGetLastError();
1220 sprintf(req
.serverError
.errormessage
, "Communication Error");
1222 req
.attempt
= UCHAR_MAX
;
1225 req
.expiry
= time(NULL
) + req
.timeout
;
1229 req
.tblock
= ntohs(req
.pkt
[1]->block
) + 1;
1230 if (req
.tblock
== req
.block
)
1232 req
.pkt
[1]->block
= htons(++req
.tblock
);
1233 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1237 req
.serverError
.opcode
= htons(5);
1238 req
.serverError
.errorcode
= htons(4);
1239 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1240 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1242 req
.attempt
= UCHAR_MAX
;
1245 else if (req
.bytesRead
[1] < req
.blksize
)
1253 else if (ntohs(req
.pkt
[1]->block
) == req
.block
)
1256 send(req
.sock
, (const char*)req
.pkt
[1], req
.bytesRead
[1] + 4, 0);
1257 errno
= WSAGetLastError();
1260 sprintf(req
.serverError
.errormessage
, "Communication Error");
1262 req
.attempt
= UCHAR_MAX
;
1266 req
.expiry
= time(NULL
) + req
.timeout
;
1270 req
.tblock
= ntohs(req
.pkt
[0]->block
) + 1;
1271 if (req
.tblock
== req
.block
)
1273 req
.pkt
[0]->block
= htons(++req
.tblock
);
1274 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1277 req
.serverError
.opcode
= htons(5);
1278 req
.serverError
.errorcode
= htons(4);
1279 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1280 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1282 req
.attempt
= UCHAR_MAX
;
1285 else if (req
.bytesRead
[0] < req
.blksize
)
1295 sprintf(req
.serverError
.errormessage
, "%u Blocks Served", req
.fblock
- 1);
1297 req
.attempt
= UCHAR_MAX
;
1302 else if (ntohs(req
.mesin
.opcode
) == 2)
1305 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1307 if (errno
|| !req
.pkt
[0])
1309 sprintf(req
.serverError
.errormessage
, "Memory Error");
1311 req
.attempt
= UCHAR_MAX
;
1315 while (req
.attempt
<= 3)
1317 FD_ZERO(&req
.readfds
);
1320 FD_SET(req
.sock
, &req
.readfds
);
1321 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1323 if (FD_ISSET(req
.sock
, &req
.readfds
))
1326 req
.bytesRecd
= recv(req
.sock
, (char*)req
.pkt
[0], req
.blksize
+ 4, 0);
1327 errno
= WSAGetLastError();
1331 sprintf(req
.serverError
.errormessage
, "Communication Error");
1333 req
.attempt
= UCHAR_MAX
;
1340 if (req
.bytesRecd
>= 4)
1342 if (ntohs(req
.pkt
[0]->opcode
) == 3)
1344 req
.tblock
= req
.block
+ 1;
1346 if (ntohs(req
.pkt
[0]->block
) == req
.tblock
)
1348 req
.acout
.opcode
= htons(4);
1349 req
.acout
.block
= req
.pkt
[0]->block
;
1353 req
.expiry
= time(NULL
) + req
.timeout
;
1356 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1357 errno
= WSAGetLastError();
1361 sprintf(req
.serverError
.errormessage
, "Communication Error");
1363 req
.attempt
= UCHAR_MAX
;
1367 if (req
.bytesRecd
> 4)
1370 if (fwrite(&req
.pkt
[0]->buffer
, req
.bytesRecd
- 4, 1, req
.file
) != 1 || errno
)
1372 req
.serverError
.opcode
= htons(5);
1373 req
.serverError
.errorcode
= htons(3);
1374 strcpy(req
.serverError
.errormessage
, "Disk full or allocation exceeded");
1375 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1377 req
.attempt
= UCHAR_MAX
;
1386 if ((MYWORD
)req
.bytesRecd
< req
.blksize
+ 4)
1390 sprintf(req
.serverError
.errormessage
, "%u Blocks Received", req
.fblock
);
1392 req
.attempt
= UCHAR_MAX
;
1396 else if (req
.expiry
> time(NULL
))
1398 else if (req
.attempt
>= 3)
1400 req
.serverError
.opcode
= htons(5);
1401 req
.serverError
.errorcode
= htons(0);
1403 if (req
.fblock
&& !req
.block
)
1404 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1406 strcpy(req
.serverError
.errormessage
, "Timeout");
1409 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1410 req
.attempt
= UCHAR_MAX
;
1415 req
.expiry
= time(NULL
) + req
.timeout
;
1417 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1418 errno
= WSAGetLastError();
1423 sprintf(req
.serverError
.errormessage
, "Communication Error");
1425 req
.attempt
= UCHAR_MAX
;
1430 else if (req
.bytesRecd
> (int)sizeof(message
))
1432 req
.serverError
.opcode
= htons(5);
1433 req
.serverError
.errorcode
= htons(4);
1434 sprintf(req
.serverError
.errormessage
, "Error: Incoming Packet too large");
1435 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1437 req
.attempt
= UCHAR_MAX
;
1440 else if (ntohs(req
.pkt
[0]->opcode
) == 5)
1442 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.pkt
[0]->block
), &req
.pkt
[0]->buffer
);
1444 req
.attempt
= UCHAR_MAX
;
1449 req
.serverError
.opcode
= htons(5);
1450 req
.serverError
.errorcode
= htons(4);
1451 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.pkt
[0]->opcode
));
1452 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1454 req
.attempt
= UCHAR_MAX
;
1458 else if (req
.expiry
> time(NULL
))
1460 else if (req
.attempt
>= 3)
1462 req
.serverError
.opcode
= htons(5);
1463 req
.serverError
.errorcode
= htons(0);
1465 if (req
.fblock
&& !req
.block
)
1466 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1468 strcpy(req
.serverError
.errormessage
, "Timeout");
1471 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1472 req
.attempt
= UCHAR_MAX
;
1477 req
.expiry
= time(NULL
) + req
.timeout
;
1479 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1480 errno
= WSAGetLastError();
1485 sprintf(req
.serverError
.errormessage
, "Communication Error");
1487 req
.attempt
= UCHAR_MAX
;
1494 while (cleanReq(&req
));
1496 WaitForSingleObject(cEvent
, INFINITE
);
1500 //printf("Thread %u Killed\n",GetCurrentThreadId());
1505 bool cleanReq(request
* req
)
1507 //printf("cleaning\n");
1512 if (!(req
->sock
== INVALID_SOCKET
))
1515 closesocket(req
->sock
);
1524 WaitForSingleObject(cEvent
, INFINITE
);
1528 //printf("cleaned\n");
1530 return (totalThreads
<= minThreads
);
1533 bool getSection(const char *sectionName
, char *buffer
, MYBYTE serial
, char *fileName
)
1535 //printf("%s=%s\n",fileName,sectionName);
1537 sprintf(section
, "[%s]", sectionName
);
1539 FILE *f
= fopen(fileName
, "rt");
1545 while (fgets(buff
, 511, f
))
1550 if (strstr(buff
, section
) == buff
)
1553 if (found
== serial
)
1555 //printf("%s=%s\n",fileName,sectionName);
1556 while (fgets(buff
, 511, f
))
1560 if (strstr(buff
, "[") == buff
)
1563 if (((*buff
) >= '0' && (*buff
) <= '9') || ((*buff
) >= 'A' && (*buff
) <= 'Z') || ((*buff
) >= 'a' && (*buff
) <= 'z') || ((*buff
) && strchr("/\\?*", (*buff
))))
1565 buffer
+= sprintf(buffer
, "%s", buff
);
1578 return (found
== serial
);
1581 FILE *openSection(const char *sectionName
, MYBYTE serial
, char *fileName
)
1583 //printf("%s=%s\n",fileName,sectionName);
1585 sprintf(section
, "[%s]", sectionName
);
1587 FILE *f
= fopen(fileName
, "rt");
1593 while (fgets(buff
, 511, f
))
1598 if (strstr(buff
, section
) == buff
)
1602 if (found
== serial
)
1611 char *readSection(char* buff
, FILE *f
)
1613 while (fgets(buff
, 511, f
))
1620 if (((*buff
) >= '0' && (*buff
) <= '9') || ((*buff
) >= 'A' && (*buff
) <= 'Z') || ((*buff
) >= 'a' && (*buff
) <= 'z') || ((*buff
) && strchr("/\\?*", (*buff
))))
1628 char* myGetToken(char* buff
, MYBYTE index
)
1637 buff
+= strlen(buff
) + 1;
1643 MYWORD
myTokenize(char *target
, char *source
, char *sep
, bool whiteSep
)
1651 if (sep
&& sep
[0] && strchr(sep
, (*source
)))
1657 else if (whiteSep
&& (*source
) <= 32)
1684 //printf("%s\n", target);
1689 char* myTrim(char *target
, char *source
)
1691 while ((*source
) && (*source
) <= 32)
1696 for (; i
< 511 && source
[i
]; i
++)
1697 target
[i
] = source
[i
];
1699 target
[i
] = source
[i
];
1702 for (; i
>= 0 && target
[i
] <= 32; i
--)
1709 void mySplit(char *name, char *value, char *source, char splitChar)
1711 char *dp = strchr(source, splitChar);
1715 strncpy(name, source, (dp - source));
1716 name[dp - source] = 0;
1717 strcpy(value, dp + 1);
1719 myTrim(value, value);
1723 strcpy(name, source);
1730 void mySplit(char *name
, char *value
, char *source
, char splitChar
)
1736 for (; source
[i
] && j
<= 510 && source
[i
] != splitChar
; i
++, j
++)
1738 name
[j
] = source
[i
];
1744 for (; k
<= 510 && source
[i
]; i
++, k
++)
1746 value
[k
] = source
[i
];
1754 myTrim(value
, value
);
1755 //printf("%s %s\n", name, value);
1759 char *IP2String(char *target
, MYDWORD ip
)
1763 sprintf(target
, "%u.%u.%u.%u", inaddr
.octate
[0], inaddr
.octate
[1], inaddr
.octate
[2], inaddr
.octate
[3]);
1767 bool isIP(char *string
)
1771 for (; *string
; string
++)
1773 if (*string
== '.' && *(string
+ 1) != '.')
1775 else if (*string
< '0' || *string
> '9')
1785 char *myUpper(char *string
)
1787 char diff
= 'a' - 'A';
1788 MYWORD len
= strlen(string
);
1789 for (int i
= 0; i
< len
; i
++)
1790 if (string
[i
] >= 'a' && string
[i
] <= 'z')
1795 char *myLower(char *string
)
1797 char diff
= 'a' - 'A';
1798 MYWORD len
= strlen(string
);
1799 for (int i
= 0; i
< len
; i
++)
1800 if (string
[i
] >= 'A' && string
[i
] <= 'Z')
1805 void init(void *lpParam
)
1807 memset(&cfig
, 0, sizeof(cfig
));
1809 GetModuleFileName(NULL
, extbuff
, _MAX_PATH
);
1810 char *fileExt
= strrchr(extbuff
, '.');
1812 sprintf(iniFile
, "%s.ini", extbuff
);
1813 sprintf(lnkFile
, "%s.url", extbuff
);
1814 fileExt
= strrchr(extbuff
, '\\');
1817 sprintf(logFile
, "%s\\log\\%s%%Y%%m%%d.log", extbuff
, fileExt
);
1827 printf("%s\n\n", sVersion
);
1829 else if ((f
= openSection("LOGGING", 1, iniFile
)))
1834 while (readSection(raw
, f
))
1836 if (!strcasecmp(raw
, "None"))
1838 else if (!strcasecmp(raw
, "Errors"))
1840 else if (!strcasecmp(raw
, "All"))
1843 sprintf(tempbuff
, "Section [LOGGING], Invalid LogLevel: %s", raw
);
1847 if (!verbatim
&& cfig
.logLevel
&& logFile
[0])
1849 time_t t
= time(NULL
);
1850 tm
*ttm
= localtime(&t
);
1851 loggingDay
= ttm
->tm_yday
;
1852 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
1854 cfig
.logfile
= fopen(extbuff
, "at");
1858 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
1859 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
1860 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
1861 sprintf(logBuff
, "%s Starting..", sVersion
);
1862 logMess(logBuff
, 1);
1865 logMess(tempbuff
, 0);
1869 MYWORD wVersionRequested
= MAKEWORD(1, 1);
1870 WSAStartup(wVersionRequested
, &cfig
.wsaData
);
1872 if (cfig
.wsaData
.wVersion
!= wVersionRequested
)
1874 sprintf(logBuff
, "WSAStartup Error");
1875 logMess(logBuff
, 1);
1878 if ((f
= openSection("HOME", 1, iniFile
)))
1880 while (readSection(raw
, f
))
1882 mySplit(name
, value
, raw
, '=');
1886 if (!cfig
.homes
[0].alias
[0] && cfig
.homes
[0].target
[0])
1888 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", raw
);
1889 logMess(logBuff
, 1);
1891 else if (strchr(name
, notFileSep
) || strchr(name
, fileSep
) || strchr(name
, '>') || strchr(name
, '<') || strchr(name
, '.'))
1893 sprintf(logBuff
, "Section [HOME], invalid chars in alias %s, entry ignored", name
);
1894 logMess(logBuff
, 1);
1896 else if (name
[0] && strlen(name
) < 64 && value
[0])
1899 for (int i
= 0; i
< MAX_SERVERS
; i
++)
1901 for (int i
= 0; i
< 8; i
++)
1904 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(name
, cfig
.homes
[i
].alias
))
1906 sprintf(logBuff
, "Section [HOME], Duplicate Entry: %s ignored", raw
);
1907 logMess(logBuff
, 1);
1910 else if (!cfig
.homes
[i
].alias
[0])
1912 strcpy(cfig
.homes
[i
].alias
, name
);
1913 strcpy(cfig
.homes
[i
].target
, value
);
1915 if (cfig
.homes
[i
].target
[strlen(cfig
.homes
[i
].target
) - 1] != fileSep
)
1917 tempbuff
[0] = fileSep
;
1919 strcat(cfig
.homes
[i
].target
, tempbuff
);
1928 sprintf(logBuff
, "Section [HOME], alias %s too large", name
);
1929 logMess(logBuff
, 1);
1932 else if (!cfig
.homes
[0].alias
[0] && !cfig
.homes
[0].target
[0])
1934 strcpy(cfig
.homes
[0].target
, name
);
1936 if (cfig
.homes
[0].target
[strlen(cfig
.homes
[0].target
) - 1] != fileSep
)
1938 tempbuff
[0] = fileSep
;
1940 strcat(cfig
.homes
[0].target
, tempbuff
);
1943 else if (cfig
.homes
[0].alias
[0])
1945 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", raw
);
1946 logMess(logBuff
, 1);
1948 else if (cfig
.homes
[0].target
[0])
1950 sprintf(logBuff
, "Section [HOME], Duplicate Path: %s ignored", raw
);
1951 logMess(logBuff
, 1);
1955 sprintf(logBuff
, "Section [HOME], missing = sign, Invalid Entry: %s ignored", raw
);
1956 logMess(logBuff
, 1);
1961 if (!cfig
.homes
[0].target
[0])
1963 GetModuleFileName(NULL
, cfig
.homes
[0].target
, UCHAR_MAX
);
1964 char *iniFileExt
= strrchr(cfig
.homes
[0].target
, fileSep
);
1965 *(++iniFileExt
) = 0;
1968 cfig
.fileRead
= true;
1970 if ((f
= openSection("TFTP-OPTIONS", 1, iniFile
)))
1972 while (readSection(raw
, f
))
1974 mySplit(name
, value
, raw
, '=');
1978 if (!strcasecmp(name
, "blksize"))
1980 MYDWORD tblksize
= atol(value
);
1984 else if (tblksize
> USHRT_MAX
- 32)
1985 blksize
= USHRT_MAX
- 32;
1989 else if (!strcasecmp(name
, "threadpoolsize"))
1991 minThreads
= atol(value
);
1994 else if (minThreads
> 100)
1997 else if (!strcasecmp(name
, "timeout"))
1999 timeout
= atol(value
);
2002 else if (timeout
> UCHAR_MAX
)
2003 timeout
= UCHAR_MAX
;
2005 else if (!strcasecmp(name
, "Read"))
2007 if (strchr("Yy", *value
))
2008 cfig
.fileRead
= true;
2010 cfig
.fileRead
= false;
2012 else if (!strcasecmp(name
, "Write"))
2014 if (strchr("Yy", *value
))
2015 cfig
.fileWrite
= true;
2017 cfig
.fileWrite
= false;
2019 else if (!strcasecmp(name
, "Overwrite"))
2021 if (strchr("Yy", *value
))
2022 cfig
.fileOverwrite
= true;
2024 cfig
.fileOverwrite
= false;
2026 else if (!strcasecmp(name
, "port-range"))
2028 char *ptr
= strchr(value
, '-');
2032 cfig
.minport
= atol(value
);
2033 cfig
.maxport
= atol(++ptr
);
2035 if (cfig
.minport
< 1024 || cfig
.minport
>= USHRT_MAX
|| cfig
.maxport
< 1024 || cfig
.maxport
>= USHRT_MAX
|| cfig
.minport
> cfig
.maxport
)
2040 sprintf(logBuff
, "Invalid port range %s", value
);
2041 logMess(logBuff
, 1);
2046 sprintf(logBuff
, "Invalid port range %s", value
);
2047 logMess(logBuff
, 1);
2052 sprintf(logBuff
, "Warning: unknown option %s, ignored", name
);
2053 logMess(logBuff
, 1);
2059 if ((f
= openSection("ALLOWED-CLIENTS", 1, iniFile
)))
2067 while (readSection(raw
, f
))
2070 if (i
< _countof(cfig
.hostRanges
))
2077 mySplit(name
, value
, raw
, '-');
2078 rs
= htonl(my_inet_addr(name
));
2081 re
= htonl(my_inet_addr(value
));
2085 if (rs
&& rs
!= INADDR_NONE
&& re
&& re
!= INADDR_NONE
&& rs
<= re
)
2087 cfig
.hostRanges
[i
].rangeStart
= rs
;
2088 cfig
.hostRanges
[i
].rangeEnd
= re
;
2093 sprintf(logBuff
, "Section [ALLOWED-CLIENTS] Invalid entry %s in ini file, ignored", raw
);
2094 logMess(logBuff
, 1);
2102 printf("starting TFTP...\n");
2106 sprintf(logBuff
, "starting TFTP service");
2107 logMess(logBuff
, 1);
2110 for (int i
= 0; i
< MAX_SERVERS
; i
++)
2111 if (cfig
.homes
[i
].target
[0])
2113 sprintf(logBuff
, "alias /%s is mapped to %s", cfig
.homes
[i
].alias
, cfig
.homes
[i
].target
);
2114 logMess(logBuff
, 1);
2117 if (cfig
.hostRanges
[0].rangeStart
)
2122 for (MYWORD i
= 0; i
< _countof(cfig
.hostRanges
) && cfig
.hostRanges
[i
].rangeStart
; i
++)
2124 for (MYWORD i
= 0; i
<= sizeof(cfig
.hostRanges
) && cfig
.hostRanges
[i
].rangeStart
; i
++)
2127 sprintf(logBuff
, "%s", "permitted clients: ");
2128 sprintf(temp
, "%s-", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeStart
)));
2129 strcat(logBuff
, temp
);
2130 sprintf(temp
, "%s", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeEnd
)));
2131 strcat(logBuff
, temp
);
2132 logMess(logBuff
, 1);
2137 sprintf(logBuff
, "%s", "permitted clients: all");
2138 logMess(logBuff
, 1);
2143 sprintf(logBuff
, "server port range: %u-%u", cfig
.minport
, cfig
.maxport
);
2144 logMess(logBuff
, 1);
2148 sprintf(logBuff
, "server port range: all");
2149 logMess(logBuff
, 1);
2152 sprintf(logBuff
, "max blksize: %u", blksize
);
2153 logMess(logBuff
, 1);
2154 sprintf(logBuff
, "default blksize: %u", 512);
2155 logMess(logBuff
, 1);
2156 sprintf(logBuff
, "default timeout: %u", timeout
);
2157 logMess(logBuff
, 1);
2158 sprintf(logBuff
, "file read allowed: %s", cfig
.fileRead
? "Yes" : "No");
2159 logMess(logBuff
, 1);
2160 sprintf(logBuff
, "file create allowed: %s", cfig
.fileWrite
? "Yes" : "No");
2161 logMess(logBuff
, 1);
2162 sprintf(logBuff
, "file overwrite allowed: %s", cfig
.fileOverwrite
? "Yes" : "No");
2163 logMess(logBuff
, 1);
2167 sprintf(logBuff
, "logging: %s", cfig
.logLevel
> 1 ? "all" : "errors");
2168 logMess(logBuff
, 1);
2171 lEvent
= CreateEvent(
2172 NULL
, // default security descriptor
2173 FALSE
, // ManualReset
2175 TEXT("AchalTFTServerLogEvent")); // object name
2179 printf("CreateEvent error: %lu\n", GetLastError());
2182 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2184 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2185 logMess(logBuff
, 0);
2189 tEvent
= CreateEvent(
2190 NULL
, // default security descriptor
2191 FALSE
, // ManualReset
2193 TEXT("AchalTFTServerThreadEvent")); // object name
2197 printf("CreateEvent error: %lu\n", GetLastError());
2200 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2202 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2203 logMess(logBuff
, 0);
2207 sEvent
= CreateEvent(
2208 NULL
, // default security descriptor
2209 FALSE
, // ManualReset
2211 TEXT("AchalTFTServerSocketEvent")); // object name
2215 printf("CreateEvent error: %lu\n", GetLastError());
2218 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2220 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2221 logMess(logBuff
, 0);
2225 cEvent
= CreateEvent(
2226 NULL
, // default security descriptor
2227 FALSE
, // ManualReset
2229 TEXT("AchalTFTServerCountEvent")); // object name
2233 printf("CreateEvent error: %lu\n", GetLastError());
2236 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2238 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2239 logMess(logBuff
, 0);
2245 for (int i
= 0; i
< minThreads
; i
++)
2248 processRequest
, // thread function
2249 0, // default security attributes
2250 NULL
); // argument to thread function
2253 sprintf(logBuff
, "thread pool size: %u", minThreads
);
2254 logMess(logBuff
, 1);
2257 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].port
; i
++)
2259 sprintf(logBuff
, "listening on: %s:%i", IP2String(tempbuff
, network
.tftpConn
[i
].server
), network
.tftpConn
[i
].port
);
2260 logMess(logBuff
, 1);
2265 memset(&newNetwork
, 0, sizeof(data1
));
2267 bool bindfailed
= false;
2269 if ((f
= openSection("LISTEN-ON", 1, iniFile
)))
2273 while (readSection(raw
, f
))
2277 cfig
.ifspecified
= true;
2278 mySplit(name
, value
, raw
, ':');
2287 MYDWORD addr
= my_inet_addr(name
);
2291 newNetwork
.listenServers
[0] = 0;
2292 newNetwork
.listenPorts
[0] = port
;
2296 else if (!findServer(newNetwork
.listenServers
, addr
))
2298 newNetwork
.listenServers
[i
] = addr
;
2299 newNetwork
.listenPorts
[i
] = port
;
2305 sprintf(logBuff
, "Warning: Section [LISTEN-ON], Invalid Interface Address %s, ignored", raw
);
2306 logMess(logBuff
, 1);
2312 if (!cfig
.ifspecified
)
2314 sprintf(logBuff
, "detecting Interfaces..");
2315 logMess(logBuff
, 1);
2316 getInterfaces(&newNetwork
);
2318 for (MYBYTE n
= 0; n
< MAX_SERVERS
&& newNetwork
.staticServers
[n
]; n
++)
2320 newNetwork
.listenServers
[n
] = newNetwork
.staticServers
[n
];
2321 newNetwork
.listenPorts
[n
] = 69;
2327 for (int j
= 0; j
< MAX_SERVERS
&& newNetwork
.listenPorts
[j
]; j
++)
2331 for (; k
< MAX_SERVERS
&& network
.tftpConn
[k
].loaded
; k
++)
2333 if (network
.tftpConn
[k
].ready
&& network
.tftpConn
[k
].server
== newNetwork
.listenServers
[j
] && network
.tftpConn
[k
].port
== newNetwork
.listenPorts
[j
])
2337 if (network
.tftpConn
[k
].ready
&& network
.tftpConn
[k
].server
== newNetwork
.listenServers
[j
] && network
.tftpConn
[k
].port
== newNetwork
.listenPorts
[j
])
2339 memcpy(&(newNetwork
.tftpConn
[i
]), &(network
.tftpConn
[k
]), sizeof(tftpConnType
));
2341 if (newNetwork
.maxFD
< newNetwork
.tftpConn
[i
].sock
)
2342 newNetwork
.maxFD
= newNetwork
.tftpConn
[i
].sock
;
2344 network
.tftpConn
[k
].ready
= false;
2345 //printf("%d, %s found\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2351 newNetwork
.tftpConn
[i
].sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
2353 if (newNetwork
.tftpConn
[i
].sock
== INVALID_SOCKET
)
2356 sprintf(logBuff
, "Failed to Create Socket");
2357 logMess(logBuff
, 1);
2361 //printf("Socket %u\n", newNetwork.tftpConn[i].sock);
2364 newNetwork
.tftpConn
[i
].addr
.sin_family
= AF_INET
;
2365 newNetwork
.tftpConn
[i
].addr
.sin_addr
.s_addr
= newNetwork
.listenServers
[j
];
2366 newNetwork
.tftpConn
[i
].addr
.sin_port
= htons(newNetwork
.listenPorts
[j
]);
2367 int nRet
= bind(newNetwork
.tftpConn
[i
].sock
, (sockaddr
*)&newNetwork
.tftpConn
[i
].addr
, sizeof(struct sockaddr_in
));
2369 if (nRet
== SOCKET_ERROR
|| errno
)
2372 closesocket(newNetwork
.tftpConn
[i
].sock
);
2373 sprintf(logBuff
, "%s Port %i bind failed", IP2String(tempbuff
, newNetwork
.listenServers
[j
]), newNetwork
.listenPorts
[j
]);
2374 logMess(logBuff
, 1);
2378 newNetwork
.tftpConn
[i
].loaded
= true;
2379 newNetwork
.tftpConn
[i
].ready
= true;
2380 newNetwork
.tftpConn
[i
].server
= newNetwork
.listenServers
[j
];
2381 newNetwork
.tftpConn
[i
].port
= newNetwork
.listenPorts
[j
];
2383 //printf("%d, %s created\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2385 if (newNetwork
.maxFD
< newNetwork
.tftpConn
[i
].sock
)
2386 newNetwork
.maxFD
= newNetwork
.tftpConn
[i
].sock
;
2388 if (!newNetwork
.listenServers
[j
])
2396 cfig
.failureCount
++;
2398 cfig
.failureCount
= 0;
2401 memcpy(&network
, &newNetwork
, sizeof(data1
));
2403 //printf("%i %i %i\n", network.tftpConn[0].ready, network.dnsUdpConn[0].ready, network.dnsTcpConn[0].ready);
2405 if (!network
.tftpConn
[0].ready
)
2407 sprintf(logBuff
, "No Static Interface ready, Waiting...");
2408 logMess(logBuff
, 1);
2412 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].loaded
; i
++)
2414 sprintf(logBuff
, "Listening On: %s:%d", IP2String(tempbuff
, network
.tftpConn
[i
].server
), network
.tftpConn
[i
].port
);
2415 logMess(logBuff
, 1);
2418 network
.ready
= true;
2420 } while (detectChange());
2422 //printf("Exiting Init\n");
2430 if (!cfig
.failureCount
)
2432 if (cfig
.ifspecified
)
2436 MYDWORD eventWait
= UINT_MAX
;
2438 if (cfig
.failureCount
)
2440 eventWait
= 10000 * (1 << cfig
.failureCount
);
2442 eventWait
= 10000 * pow(2, cfig
.failureCount
);
2448 overlap
.hEvent
= WSACreateEvent();
2450 ret
= NotifyAddrChange(&hand
, &overlap
);
2452 if (ret
!= NO_ERROR
)
2454 if (WSAGetLastError() != WSA_IO_PENDING
)
2456 printf("NotifyAddrChange error...%d\n", WSAGetLastError());
2461 if ( WaitForSingleObject(overlap
.hEvent
, eventWait
) == WAIT_OBJECT_0
)
2462 WSACloseEvent(overlap
.hEvent
);
2464 network
.ready
= false;
2466 while (network
.busy
)
2469 if (cfig
.failureCount
)
2471 sprintf(logBuff
, "Retrying failed Listening Interfaces..");
2472 logMess(logBuff
, 1);
2476 sprintf(logBuff
, "Network changed, re-detecting Interfaces..");
2477 logMess(logBuff
, 1);
2484 void getInterfaces(data1 *network)
2486 memset(network, 0, sizeof(data1));
2488 SOCKET sd = WSASocket(PF_INET, SOCK_DGRAM, 0, 0, 0, 0);
2490 if (sd == INVALID_SOCKET)
2493 INTERFACE_INFO InterfaceList[MAX_SERVERS];
2494 unsigned long nBytesReturned;
2496 if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
2497 sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
2500 int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
2502 for (int i = 0; i < nNumInterfaces; ++i)
2504 sockaddr_in *pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress);
2505 u_long nFlags = InterfaceList[i].iiFlags;
2507 if (!(nFlags & IFF_POINTTOPOINT))
2509 //printf("%s\n", IP2String(tempbuff, pAddress->sin_addr.S_un.S_addr));
2510 addServer(network->staticServers, pAddress->sin_addr.s_addr);
2519 void getInterfaces(data1
*network
)
2521 memset(network
, 0, sizeof(data1
));
2523 SOCKET sd
= WSASocket(PF_INET
, SOCK_DGRAM
, 0, 0, 0, 0);
2525 if (sd
== INVALID_SOCKET
)
2528 INTERFACE_INFO InterfaceList
[MAX_SERVERS
];
2529 unsigned long nBytesReturned
;
2531 if (WSAIoctl(sd
, SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
,
2532 sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
2535 int nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
2537 for (int i
= 0; i
< nNumInterfaces
; ++i
)
2539 sockaddr_in
*pAddress
= (sockaddr_in
*)&(InterfaceList
[i
].iiAddress
);
2540 u_long nFlags
= InterfaceList
[i
].iiFlags
;
2542 if (pAddress
->sin_addr
.s_addr
)
2544 addServer(network
->allServers
, pAddress
->sin_addr
.s_addr
);
2546 if (!(nFlags
& IFF_POINTTOPOINT
) && (nFlags
& IFF_UP
))
2548 addServer(network
->staticServers
, pAddress
->sin_addr
.s_addr
);
2557 bool addServer(MYDWORD
*array
, MYDWORD ip
)
2559 for (MYBYTE i
= 0; i
< MAX_SERVERS
; i
++)
2561 if (!ip
|| array
[i
] == ip
)
2572 MYDWORD
*findServer(MYDWORD
*array
, MYDWORD ip
)
2576 for (MYBYTE i
= 0; i
< MAX_SERVERS
&& array
[i
]; i
++)
2585 void logMess(char *logBuff
, MYBYTE logLevel
)
2587 WaitForSingleObject(lEvent
, INFINITE
);
2590 printf("%s\n", logBuff
);
2591 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2593 time_t t
= time(NULL
);
2594 tm
*ttm
= localtime(&t
);
2596 if (ttm
->tm_yday
!= loggingDay
)
2598 loggingDay
= ttm
->tm_yday
;
2599 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
2600 fprintf(cfig
.logfile
, "Logging Continued on file %s\n", extbuff
);
2601 fclose(cfig
.logfile
);
2602 cfig
.logfile
= fopen(extbuff
, "at");
2606 fprintf(cfig
.logfile
, "%s\n\n", sVersion
);
2607 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
2608 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
2609 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
2615 strftime(extbuff
, sizeof(extbuff
), "%d-%b-%y %X", ttm
);
2616 fprintf(cfig
.logfile
, "[%s] %s\n", extbuff
, logBuff
);
2617 fflush(cfig
.logfile
);
2622 void logMess(request
*req
, MYBYTE logLevel
)
2624 WaitForSingleObject(lEvent
, INFINITE
);
2630 if (!req
->serverError
.errormessage
[0])
2631 sprintf(req
->serverError
.errormessage
, strerror(errno
));
2634 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
);
2636 printf("Client %s:%u, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2638 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2640 time_t t
= time(NULL
);
2641 tm
*ttm
= localtime(&t
);
2643 if (ttm
->tm_yday
!= loggingDay
)
2645 loggingDay
= ttm
->tm_yday
;
2646 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
2647 fprintf(cfig
.logfile
, "Logging Continued on file %s\n", extbuff
);
2648 fclose(cfig
.logfile
);
2649 cfig
.logfile
= fopen(extbuff
, "at");
2653 fprintf(cfig
.logfile
, "%s\n\n", sVersion
);
2654 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
2655 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
2656 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
2662 strftime(extbuff
, sizeof(extbuff
), "%d-%b-%y %X", ttm
);
2665 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
);
2667 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
);
2669 fflush(cfig
.logfile
);