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;
543 for (int j
= 0; j
<= 32 && cfig
.hostRanges
[j
].rangeStart
; j
++)
545 if (iip
>= cfig
.hostRanges
[j
].rangeStart
&& iip
<= cfig
.hostRanges
[j
].rangeEnd
)
554 req
.serverError
.opcode
= htons(5);
555 req
.serverError
.errorcode
= htons(2);
556 strcpy(req
.serverError
.errormessage
, "Access Denied");
558 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
559 req
.attempt
= UCHAR_MAX
;
564 if ((htons(req
.mesin
.opcode
) == 5))
566 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.clientError
.errorcode
), req
.clientError
.errormessage
);
568 req
.attempt
= UCHAR_MAX
;
571 else if (htons(req
.mesin
.opcode
) != 1 && htons(req
.mesin
.opcode
) != 2)
573 req
.serverError
.opcode
= htons(5);
574 req
.serverError
.errorcode
= htons(5);
575 sprintf(req
.serverError
.errormessage
, "Unknown Transfer Id");
577 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
578 req
.attempt
= UCHAR_MAX
;
584 sprintf(req
.serverError
.errormessage
, "Communication Error");
586 req
.attempt
= UCHAR_MAX
;
591 req
.timeout
= timeout
;
592 req
.expiry
= time(NULL
) + req
.timeout
;
593 bool fetchAck
= false;
595 req
.sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
597 if (req
.sock
== INVALID_SOCKET
)
599 req
.serverError
.opcode
= htons(5);
600 req
.serverError
.errorcode
= htons(0);
601 strcpy(req
.serverError
.errormessage
, "Thread Socket Creation Error");
602 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
604 req
.attempt
= UCHAR_MAX
;
609 service
.sin_family
= AF_INET
;
610 service
.sin_addr
.s_addr
= network
.tftpConn
[req
.sockInd
].server
;
614 for (MYWORD comport
= cfig
.minport
; ; comport
++)
616 service
.sin_port
= htons(comport
);
618 if (comport
> cfig
.maxport
)
620 req
.serverError
.opcode
= htons(5);
621 req
.serverError
.errorcode
= htons(0);
622 strcpy(req
.serverError
.errormessage
, "No port is free");
623 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
625 req
.attempt
= UCHAR_MAX
;
628 else if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
636 service
.sin_port
= 0;
638 if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
640 strcpy(req
.serverError
.errormessage
, "Thread failed to bind");
641 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
643 req
.attempt
= UCHAR_MAX
;
647 if (req
.attempt
>= 3)
650 if (connect(req
.sock
, (sockaddr
*)&req
.client
, req
.clientsize
) == -1)
652 req
.serverError
.opcode
= htons(5);
653 req
.serverError
.errorcode
= htons(0);
654 strcpy(req
.serverError
.errormessage
, "Connect Failed");
655 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
657 req
.attempt
= UCHAR_MAX
;
661 //sprintf(req.serverError.errormessage, "In Temp, Socket");
664 char *inPtr
= req
.mesin
.buffer
;
665 *(inPtr
+ (req
.bytesRecd
- 3)) = 0;
666 req
.filename
= inPtr
;
668 if (!strlen(req
.filename
) || strlen(req
.filename
) > UCHAR_MAX
)
670 req
.serverError
.opcode
= htons(5);
671 req
.serverError
.errorcode
= htons(4);
672 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Filename");
673 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
674 req
.attempt
= UCHAR_MAX
;
679 inPtr
+= strlen(inPtr
) + 1;
682 if (!strlen(req
.mode
) || strlen(req
.mode
) > 25)
684 req
.serverError
.opcode
= htons(5);
685 req
.serverError
.errorcode
= htons(4);
686 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Mode");
687 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
688 req
.attempt
= UCHAR_MAX
;
693 inPtr
+= strlen(inPtr
) + 1;
695 for (MYDWORD i
= 0; i
< strlen(req
.filename
); i
++)
696 if (req
.filename
[i
] == notFileSep
)
697 req
.filename
[i
] = fileSep
;
701 tempbuff
[2] = fileSep
;
704 if (strstr(req
.filename
, tempbuff
))
706 req
.serverError
.opcode
= htons(5);
707 req
.serverError
.errorcode
= htons(2);
708 strcpy(req
.serverError
.errormessage
, "Access violation");
709 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
711 req
.attempt
= UCHAR_MAX
;
715 if (req
.filename
[0] == fileSep
)
718 if (!cfig
.homes
[0].alias
[0])
720 if (strlen(cfig
.homes
[0].target
) + strlen(req
.filename
) >= sizeof(req
.path
))
722 req
.serverError
.opcode
= htons(5);
723 req
.serverError
.errorcode
= htons(4);
724 sprintf(req
.serverError
.errormessage
, "Filename too large");
725 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
727 req
.attempt
= UCHAR_MAX
;
731 strcpy(req
.path
, cfig
.homes
[0].target
);
732 strcat(req
.path
, req
.filename
);
736 char *bname
= strchr(req
.filename
, fileSep
);
745 req
.serverError
.opcode
= htons(5);
746 req
.serverError
.errorcode
= htons(2);
747 sprintf(req
.serverError
.errormessage
, "Missing directory/alias");
748 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
750 req
.attempt
= UCHAR_MAX
;
754 for (int i
= 0; i
< 8; i
++)
756 //printf("%s=%i\n", req.filename, cfig.homes[i].alias[0]);
757 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(req
.filename
, cfig
.homes
[i
].alias
))
759 if (strlen(cfig
.homes
[i
].target
) + strlen(bname
) >= sizeof(req
.path
))
761 req
.serverError
.opcode
= htons(5);
762 req
.serverError
.errorcode
= htons(4);
763 sprintf(req
.serverError
.errormessage
, "Filename too large");
764 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
766 req
.attempt
= UCHAR_MAX
;
770 strcpy(req
.path
, cfig
.homes
[i
].target
);
771 strcat(req
.path
, bname
);
774 else if (i
== 7 || !cfig
.homes
[i
].alias
[0])
776 req
.serverError
.opcode
= htons(5);
777 req
.serverError
.errorcode
= htons(2);
778 sprintf(req
.serverError
.errormessage
, "No such directory/alias %s", req
.filename
);
779 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
781 req
.attempt
= UCHAR_MAX
;
787 if (req
.attempt
>= 3)
790 if (ntohs(req
.mesin
.opcode
) == 1)
794 req
.serverError
.opcode
= htons(5);
795 req
.serverError
.errorcode
= htons(2);
796 strcpy(req
.serverError
.errormessage
, "GET Access Denied");
798 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
799 req
.attempt
= UCHAR_MAX
;
809 if (!strcasecmp(tmp
, "blksize"))
811 tmp
+= strlen(tmp
) + 1;
812 MYDWORD val
= atol(tmp
);
816 else if (val
> blksize
)
823 tmp
+= strlen(tmp
) + 1;
829 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
830 req
.file
= fopen(req
.path
, "rt");
832 req
.file
= fopen(req
.path
, "rb");
834 if (errno
|| !req
.file
)
836 req
.serverError
.opcode
= htons(5);
837 req
.serverError
.errorcode
= htons(1);
838 strcpy(req
.serverError
.errormessage
, "File not found or No Access");
840 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
841 req
.attempt
= UCHAR_MAX
;
847 if (!cfig
.fileWrite
&& !cfig
.fileOverwrite
)
849 req
.serverError
.opcode
= htons(5);
850 req
.serverError
.errorcode
= htons(2);
851 strcpy(req
.serverError
.errormessage
, "PUT Access Denied");
852 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
854 req
.attempt
= UCHAR_MAX
;
858 req
.file
= fopen(req
.path
, "rb");
865 if (!cfig
.fileOverwrite
)
867 req
.serverError
.opcode
= htons(5);
868 req
.serverError
.errorcode
= htons(6);
869 strcpy(req
.serverError
.errormessage
, "File already exists");
870 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
872 req
.attempt
= UCHAR_MAX
;
876 else if (!cfig
.fileWrite
)
878 req
.serverError
.opcode
= htons(5);
879 req
.serverError
.errorcode
= htons(2);
880 strcpy(req
.serverError
.errormessage
, "Create File Access Denied");
881 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
883 req
.attempt
= UCHAR_MAX
;
889 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
890 req
.file
= fopen(req
.path
, "wt");
892 req
.file
= fopen(req
.path
, "wb");
894 if (errno
|| !req
.file
)
896 req
.serverError
.opcode
= htons(5);
897 req
.serverError
.errorcode
= htons(2);
898 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
899 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
901 req
.attempt
= UCHAR_MAX
;
906 setvbuf(req
.file
, NULL
, _IOFBF
, 5 * req
.blksize
);
911 char *outPtr
= req
.mesout
.buffer
;
912 req
.mesout
.opcode
= htons(6);
916 //printf("%s\n", inPtr);
917 if (!strcasecmp(inPtr
, "blksize"))
919 strcpy(outPtr
, inPtr
);
920 outPtr
+= strlen(outPtr
) + 1;
921 inPtr
+= strlen(inPtr
) + 1;
926 else if (val
> blksize
)
930 sprintf(outPtr
, "%u", val
);
931 outPtr
+= strlen(outPtr
) + 1;
933 else if (!strcasecmp(inPtr
, "tsize"))
935 strcpy(outPtr
, inPtr
);
936 outPtr
+= strlen(outPtr
) + 1;
937 inPtr
+= strlen(inPtr
) + 1;
939 if (ntohs(req
.mesin
.opcode
) == 1)
941 if (!fseek(req
.file
, 0, SEEK_END
))
943 if (ftell(req
.file
) >= 0)
945 req
.tsize
= ftell(req
.file
);
946 sprintf(outPtr
, "%u", req
.tsize
);
947 outPtr
+= strlen(outPtr
) + 1;
951 req
.serverError
.opcode
= htons(5);
952 req
.serverError
.errorcode
= htons(2);
953 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
954 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
956 req
.attempt
= UCHAR_MAX
;
962 req
.serverError
.opcode
= htons(5);
963 req
.serverError
.errorcode
= htons(2);
964 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
965 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
967 req
.attempt
= UCHAR_MAX
;
974 sprintf(outPtr
, "%u", req
.tsize
);
975 outPtr
+= strlen(outPtr
) + 1;
978 else if (!strcasecmp(inPtr
, "timeout"))
980 strcpy(outPtr
, inPtr
);
981 outPtr
+= strlen(outPtr
) + 1;
982 inPtr
+= strlen(inPtr
) + 1;
987 else if (val
> UCHAR_MAX
)
991 req
.expiry
= time(NULL
) + req
.timeout
;
992 sprintf(outPtr
, "%u", val
);
993 outPtr
+= strlen(outPtr
) + 1;
996 inPtr
+= strlen(inPtr
) + 1;
997 //printf("=%u\n", val);
1000 if (req
.attempt
>= 3)
1004 req
.bytesReady
= (MYDWORD
)outPtr
- (MYDWORD
)&req
.mesout
;
1005 //printf("Bytes Ready=%u\n", req.bytesReady);
1006 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1007 errno
= WSAGetLastError();
1009 else if (htons(req
.mesin
.opcode
) == 2)
1011 req
.acout
.opcode
= htons(4);
1012 req
.acout
.block
= htons(0);
1015 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1016 errno
= WSAGetLastError();
1021 sprintf(req
.serverError
.errormessage
, "Communication Error");
1023 req
.attempt
= UCHAR_MAX
;
1026 else if (ntohs(req
.mesin
.opcode
) == 1)
1029 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1030 req
.pkt
[1] = (packet
*)calloc(1, req
.blksize
+ 4);
1032 if (errno
|| !req
.pkt
[0] || !req
.pkt
[1])
1034 sprintf(req
.serverError
.errormessage
, "Memory Error");
1036 req
.attempt
= UCHAR_MAX
;
1040 long ftellLoc
= ftell(req
.file
);
1044 if (fseek(req
.file
, 0, SEEK_SET
))
1046 req
.serverError
.opcode
= htons(5);
1047 req
.serverError
.errorcode
= htons(2);
1048 strcpy(req
.serverError
.errormessage
, "File Access Error");
1049 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1051 req
.attempt
= UCHAR_MAX
;
1055 else if (ftellLoc
< 0)
1057 req
.serverError
.opcode
= htons(5);
1058 req
.serverError
.errorcode
= htons(2);
1059 strcpy(req
.serverError
.errormessage
, "File Access Error");
1060 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1062 req
.attempt
= UCHAR_MAX
;
1067 req
.pkt
[0]->opcode
= htons(3);
1068 req
.pkt
[0]->block
= htons(1);
1069 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1073 req
.serverError
.opcode
= htons(5);
1074 req
.serverError
.errorcode
= htons(2);
1075 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1076 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1078 req
.attempt
= UCHAR_MAX
;
1082 if (req
.bytesRead
[0] == req
.blksize
)
1084 req
.pkt
[1]->opcode
= htons(3);
1085 req
.pkt
[1]->block
= htons(2);
1086 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1087 if (req
.bytesRead
[1] < req
.blksize
)
1101 req
.serverError
.opcode
= htons(5);
1102 req
.serverError
.errorcode
= htons(2);
1103 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1104 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1106 req
.attempt
= UCHAR_MAX
;
1110 while (req
.attempt
<= 3)
1114 FD_ZERO(&req
.readfds
);
1117 FD_SET(req
.sock
, &req
.readfds
);
1118 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1120 if (FD_ISSET(req
.sock
, &req
.readfds
))
1123 req
.bytesRecd
= recv(req
.sock
, (char*)&req
.mesin
, sizeof(message
), 0);
1124 errno
= WSAGetLastError();
1125 if (req
.bytesRecd
<= 0 || errno
)
1127 sprintf(req
.serverError
.errormessage
, "Communication Error");
1129 req
.attempt
= UCHAR_MAX
;
1132 else if(req
.bytesRecd
>= 4 && ntohs(req
.mesin
.opcode
) == 4)
1134 if (ntohs(req
.acin
.block
) == req
.block
)
1140 else if (req
.expiry
> time(NULL
))
1145 else if (ntohs(req
.mesin
.opcode
) == 5)
1147 sprintf(req
.serverError
.errormessage
, "Client %s:%u, Error Code %i at Client, %s", inet_ntoa(req
.client
.sin_addr
), ntohs(req
.client
.sin_port
), ntohs(req
.clientError
.errorcode
), req
.clientError
.errormessage
);
1149 req
.attempt
= UCHAR_MAX
;
1154 req
.serverError
.opcode
= htons(5);
1155 req
.serverError
.errorcode
= htons(4);
1156 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.mesin
.opcode
));
1157 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1159 req
.attempt
= UCHAR_MAX
;
1163 else if (req
.expiry
> time(NULL
))
1176 if (req
.attempt
>= 3)
1178 req
.serverError
.opcode
= htons(5);
1179 req
.serverError
.errorcode
= htons(0);
1181 if (req
.fblock
&& !req
.block
)
1182 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1184 strcpy(req
.serverError
.errormessage
, "Timeout");
1187 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1188 req
.attempt
= UCHAR_MAX
;
1191 else if (!req
.fblock
)
1194 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1195 errno
= WSAGetLastError();
1198 sprintf(req
.serverError
.errormessage
, "Communication Error");
1200 req
.attempt
= UCHAR_MAX
;
1203 req
.expiry
= time(NULL
) + req
.timeout
;
1205 else if (ntohs(req
.pkt
[0]->block
) == req
.block
)
1208 send(req
.sock
, (const char*)req
.pkt
[0], req
.bytesRead
[0] + 4, 0);
1209 errno
= WSAGetLastError();
1212 sprintf(req
.serverError
.errormessage
, "Communication Error");
1214 req
.attempt
= UCHAR_MAX
;
1217 req
.expiry
= time(NULL
) + req
.timeout
;
1221 req
.tblock
= ntohs(req
.pkt
[1]->block
) + 1;
1222 if (req
.tblock
== req
.block
)
1224 req
.pkt
[1]->block
= htons(++req
.tblock
);
1225 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1229 req
.serverError
.opcode
= htons(5);
1230 req
.serverError
.errorcode
= htons(4);
1231 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1232 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1234 req
.attempt
= UCHAR_MAX
;
1237 else if (req
.bytesRead
[1] < req
.blksize
)
1245 else if (ntohs(req
.pkt
[1]->block
) == req
.block
)
1248 send(req
.sock
, (const char*)req
.pkt
[1], req
.bytesRead
[1] + 4, 0);
1249 errno
= WSAGetLastError();
1252 sprintf(req
.serverError
.errormessage
, "Communication Error");
1254 req
.attempt
= UCHAR_MAX
;
1258 req
.expiry
= time(NULL
) + req
.timeout
;
1262 req
.tblock
= ntohs(req
.pkt
[0]->block
) + 1;
1263 if (req
.tblock
== req
.block
)
1265 req
.pkt
[0]->block
= htons(++req
.tblock
);
1266 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1269 req
.serverError
.opcode
= htons(5);
1270 req
.serverError
.errorcode
= htons(4);
1271 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1272 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1274 req
.attempt
= UCHAR_MAX
;
1277 else if (req
.bytesRead
[0] < req
.blksize
)
1287 sprintf(req
.serverError
.errormessage
, "%u Blocks Served", req
.fblock
- 1);
1289 req
.attempt
= UCHAR_MAX
;
1294 else if (ntohs(req
.mesin
.opcode
) == 2)
1297 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1299 if (errno
|| !req
.pkt
[0])
1301 sprintf(req
.serverError
.errormessage
, "Memory Error");
1303 req
.attempt
= UCHAR_MAX
;
1307 while (req
.attempt
<= 3)
1309 FD_ZERO(&req
.readfds
);
1312 FD_SET(req
.sock
, &req
.readfds
);
1313 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1315 if (FD_ISSET(req
.sock
, &req
.readfds
))
1318 req
.bytesRecd
= recv(req
.sock
, (char*)req
.pkt
[0], req
.blksize
+ 4, 0);
1319 errno
= WSAGetLastError();
1323 sprintf(req
.serverError
.errormessage
, "Communication Error");
1325 req
.attempt
= UCHAR_MAX
;
1332 if (req
.bytesRecd
>= 4)
1334 if (ntohs(req
.pkt
[0]->opcode
) == 3)
1336 req
.tblock
= req
.block
+ 1;
1338 if (ntohs(req
.pkt
[0]->block
) == req
.tblock
)
1340 req
.acout
.opcode
= htons(4);
1341 req
.acout
.block
= req
.pkt
[0]->block
;
1345 req
.expiry
= time(NULL
) + req
.timeout
;
1348 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1349 errno
= WSAGetLastError();
1353 sprintf(req
.serverError
.errormessage
, "Communication Error");
1355 req
.attempt
= UCHAR_MAX
;
1359 if (req
.bytesRecd
> 4)
1362 if (fwrite(&req
.pkt
[0]->buffer
, req
.bytesRecd
- 4, 1, req
.file
) != 1 || errno
)
1364 req
.serverError
.opcode
= htons(5);
1365 req
.serverError
.errorcode
= htons(3);
1366 strcpy(req
.serverError
.errormessage
, "Disk full or allocation exceeded");
1367 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1369 req
.attempt
= UCHAR_MAX
;
1378 if ((MYWORD
)req
.bytesRecd
< req
.blksize
+ 4)
1382 sprintf(req
.serverError
.errormessage
, "%u Blocks Received", req
.fblock
);
1384 req
.attempt
= UCHAR_MAX
;
1388 else if (req
.expiry
> time(NULL
))
1390 else if (req
.attempt
>= 3)
1392 req
.serverError
.opcode
= htons(5);
1393 req
.serverError
.errorcode
= htons(0);
1395 if (req
.fblock
&& !req
.block
)
1396 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1398 strcpy(req
.serverError
.errormessage
, "Timeout");
1401 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1402 req
.attempt
= UCHAR_MAX
;
1407 req
.expiry
= time(NULL
) + req
.timeout
;
1409 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1410 errno
= WSAGetLastError();
1415 sprintf(req
.serverError
.errormessage
, "Communication Error");
1417 req
.attempt
= UCHAR_MAX
;
1422 else if (req
.bytesRecd
> (int)sizeof(message
))
1424 req
.serverError
.opcode
= htons(5);
1425 req
.serverError
.errorcode
= htons(4);
1426 sprintf(req
.serverError
.errormessage
, "Error: Incoming Packet too large");
1427 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1429 req
.attempt
= UCHAR_MAX
;
1432 else if (ntohs(req
.pkt
[0]->opcode
) == 5)
1434 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.pkt
[0]->block
), &req
.pkt
[0]->buffer
);
1436 req
.attempt
= UCHAR_MAX
;
1441 req
.serverError
.opcode
= htons(5);
1442 req
.serverError
.errorcode
= htons(4);
1443 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.pkt
[0]->opcode
));
1444 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1446 req
.attempt
= UCHAR_MAX
;
1450 else if (req
.expiry
> time(NULL
))
1452 else if (req
.attempt
>= 3)
1454 req
.serverError
.opcode
= htons(5);
1455 req
.serverError
.errorcode
= htons(0);
1457 if (req
.fblock
&& !req
.block
)
1458 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1460 strcpy(req
.serverError
.errormessage
, "Timeout");
1463 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1464 req
.attempt
= UCHAR_MAX
;
1469 req
.expiry
= time(NULL
) + req
.timeout
;
1471 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1472 errno
= WSAGetLastError();
1477 sprintf(req
.serverError
.errormessage
, "Communication Error");
1479 req
.attempt
= UCHAR_MAX
;
1486 while (cleanReq(&req
));
1488 WaitForSingleObject(cEvent
, INFINITE
);
1492 //printf("Thread %u Killed\n",GetCurrentThreadId());
1497 bool cleanReq(request
* req
)
1499 //printf("cleaning\n");
1504 if (!(req
->sock
== INVALID_SOCKET
))
1507 closesocket(req
->sock
);
1516 WaitForSingleObject(cEvent
, INFINITE
);
1520 //printf("cleaned\n");
1522 return (totalThreads
<= minThreads
);
1525 bool getSection(const char *sectionName
, char *buffer
, MYBYTE serial
, char *fileName
)
1527 //printf("%s=%s\n",fileName,sectionName);
1529 sprintf(section
, "[%s]", sectionName
);
1531 FILE *f
= fopen(fileName
, "rt");
1537 while (fgets(buff
, 511, f
))
1542 if (strstr(buff
, section
) == buff
)
1545 if (found
== serial
)
1547 //printf("%s=%s\n",fileName,sectionName);
1548 while (fgets(buff
, 511, f
))
1552 if (strstr(buff
, "[") == buff
)
1555 if (((*buff
) >= '0' && (*buff
) <= '9') || ((*buff
) >= 'A' && (*buff
) <= 'Z') || ((*buff
) >= 'a' && (*buff
) <= 'z') || ((*buff
) && strchr("/\\?*", (*buff
))))
1557 buffer
+= sprintf(buffer
, "%s", buff
);
1570 return (found
== serial
);
1573 FILE *openSection(const char *sectionName
, MYBYTE serial
, char *fileName
)
1575 //printf("%s=%s\n",fileName,sectionName);
1577 sprintf(section
, "[%s]", sectionName
);
1579 FILE *f
= fopen(fileName
, "rt");
1585 while (fgets(buff
, 511, f
))
1590 if (strstr(buff
, section
) == buff
)
1594 if (found
== serial
)
1603 char *readSection(char* buff
, FILE *f
)
1605 while (fgets(buff
, 511, f
))
1612 if (((*buff
) >= '0' && (*buff
) <= '9') || ((*buff
) >= 'A' && (*buff
) <= 'Z') || ((*buff
) >= 'a' && (*buff
) <= 'z') || ((*buff
) && strchr("/\\?*", (*buff
))))
1620 char* myGetToken(char* buff
, MYBYTE index
)
1629 buff
+= strlen(buff
) + 1;
1635 MYWORD
myTokenize(char *target
, char *source
, char *sep
, bool whiteSep
)
1643 if (sep
&& sep
[0] && strchr(sep
, (*source
)))
1649 else if (whiteSep
&& (*source
) <= 32)
1676 //printf("%s\n", target);
1681 char* myTrim(char *target
, char *source
)
1683 while ((*source
) && (*source
) <= 32)
1688 for (; i
< 511 && source
[i
]; i
++)
1689 target
[i
] = source
[i
];
1691 target
[i
] = source
[i
];
1694 for (; i
>= 0 && target
[i
] <= 32; i
--)
1701 void mySplit(char *name, char *value, char *source, char splitChar)
1703 char *dp = strchr(source, splitChar);
1707 strncpy(name, source, (dp - source));
1708 name[dp - source] = 0;
1709 strcpy(value, dp + 1);
1711 myTrim(value, value);
1715 strcpy(name, source);
1722 void mySplit(char *name
, char *value
, char *source
, char splitChar
)
1728 for (; source
[i
] && j
<= 510 && source
[i
] != splitChar
; i
++, j
++)
1730 name
[j
] = source
[i
];
1736 for (; k
<= 510 && source
[i
]; i
++, k
++)
1738 value
[k
] = source
[i
];
1746 myTrim(value
, value
);
1747 //printf("%s %s\n", name, value);
1751 char *IP2String(char *target
, MYDWORD ip
)
1755 sprintf(target
, "%u.%u.%u.%u", inaddr
.octate
[0], inaddr
.octate
[1], inaddr
.octate
[2], inaddr
.octate
[3]);
1759 bool isIP(char *string
)
1763 for (; *string
; string
++)
1765 if (*string
== '.' && *(string
+ 1) != '.')
1767 else if (*string
< '0' || *string
> '9')
1777 char *myUpper(char *string
)
1779 char diff
= 'a' - 'A';
1780 MYWORD len
= strlen(string
);
1781 for (int i
= 0; i
< len
; i
++)
1782 if (string
[i
] >= 'a' && string
[i
] <= 'z')
1787 char *myLower(char *string
)
1789 char diff
= 'a' - 'A';
1790 MYWORD len
= strlen(string
);
1791 for (int i
= 0; i
< len
; i
++)
1792 if (string
[i
] >= 'A' && string
[i
] <= 'Z')
1797 void init(void *lpParam
)
1799 memset(&cfig
, 0, sizeof(cfig
));
1801 GetModuleFileName(NULL
, extbuff
, _MAX_PATH
);
1802 char *fileExt
= strrchr(extbuff
, '.');
1804 sprintf(iniFile
, "%s.ini", extbuff
);
1805 sprintf(lnkFile
, "%s.url", extbuff
);
1806 fileExt
= strrchr(extbuff
, '\\');
1809 sprintf(logFile
, "%s\\log\\%s%%Y%%m%%d.log", extbuff
, fileExt
);
1819 printf("%s\n\n", sVersion
);
1821 else if ((f
= openSection("LOGGING", 1, iniFile
)))
1826 while (readSection(raw
, f
))
1828 if (!strcasecmp(raw
, "None"))
1830 else if (!strcasecmp(raw
, "Errors"))
1832 else if (!strcasecmp(raw
, "All"))
1835 sprintf(tempbuff
, "Section [LOGGING], Invalid LogLevel: %s", raw
);
1839 if (!verbatim
&& cfig
.logLevel
&& logFile
[0])
1841 time_t t
= time(NULL
);
1842 tm
*ttm
= localtime(&t
);
1843 loggingDay
= ttm
->tm_yday
;
1844 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
1846 cfig
.logfile
= fopen(extbuff
, "at");
1850 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
1851 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
1852 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
1853 sprintf(logBuff
, "%s Starting..", sVersion
);
1854 logMess(logBuff
, 1);
1857 logMess(tempbuff
, 0);
1861 MYWORD wVersionRequested
= MAKEWORD(1, 1);
1862 WSAStartup(wVersionRequested
, &cfig
.wsaData
);
1864 if (cfig
.wsaData
.wVersion
!= wVersionRequested
)
1866 sprintf(logBuff
, "WSAStartup Error");
1867 logMess(logBuff
, 1);
1870 if ((f
= openSection("HOME", 1, iniFile
)))
1872 while (readSection(raw
, f
))
1874 mySplit(name
, value
, raw
, '=');
1878 if (!cfig
.homes
[0].alias
[0] && cfig
.homes
[0].target
[0])
1880 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", raw
);
1881 logMess(logBuff
, 1);
1883 else if (strchr(name
, notFileSep
) || strchr(name
, fileSep
) || strchr(name
, '>') || strchr(name
, '<') || strchr(name
, '.'))
1885 sprintf(logBuff
, "Section [HOME], invalid chars in alias %s, entry ignored", name
);
1886 logMess(logBuff
, 1);
1888 else if (name
[0] && strlen(name
) < 64 && value
[0])
1890 for (int i
= 0; i
< 8; i
++)
1892 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(name
, cfig
.homes
[i
].alias
))
1894 sprintf(logBuff
, "Section [HOME], Duplicate Entry: %s ignored", raw
);
1895 logMess(logBuff
, 1);
1898 else if (!cfig
.homes
[i
].alias
[0])
1900 strcpy(cfig
.homes
[i
].alias
, name
);
1901 strcpy(cfig
.homes
[i
].target
, value
);
1903 if (cfig
.homes
[i
].target
[strlen(cfig
.homes
[i
].target
) - 1] != fileSep
)
1905 tempbuff
[0] = fileSep
;
1907 strcat(cfig
.homes
[i
].target
, tempbuff
);
1916 sprintf(logBuff
, "Section [HOME], alias %s too large", name
);
1917 logMess(logBuff
, 1);
1920 else if (!cfig
.homes
[0].alias
[0] && !cfig
.homes
[0].target
[0])
1922 strcpy(cfig
.homes
[0].target
, name
);
1924 if (cfig
.homes
[0].target
[strlen(cfig
.homes
[0].target
) - 1] != fileSep
)
1926 tempbuff
[0] = fileSep
;
1928 strcat(cfig
.homes
[0].target
, tempbuff
);
1931 else if (cfig
.homes
[0].alias
[0])
1933 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", raw
);
1934 logMess(logBuff
, 1);
1936 else if (cfig
.homes
[0].target
[0])
1938 sprintf(logBuff
, "Section [HOME], Duplicate Path: %s ignored", raw
);
1939 logMess(logBuff
, 1);
1943 sprintf(logBuff
, "Section [HOME], missing = sign, Invalid Entry: %s ignored", raw
);
1944 logMess(logBuff
, 1);
1949 if (!cfig
.homes
[0].target
[0])
1951 GetModuleFileName(NULL
, cfig
.homes
[0].target
, UCHAR_MAX
);
1952 char *iniFileExt
= strrchr(cfig
.homes
[0].target
, fileSep
);
1953 *(++iniFileExt
) = 0;
1956 cfig
.fileRead
= true;
1958 if ((f
= openSection("TFTP-OPTIONS", 1, iniFile
)))
1960 while (readSection(raw
, f
))
1962 mySplit(name
, value
, raw
, '=');
1966 if (!strcasecmp(name
, "blksize"))
1968 MYDWORD tblksize
= atol(value
);
1972 else if (tblksize
> USHRT_MAX
- 32)
1973 blksize
= USHRT_MAX
- 32;
1977 else if (!strcasecmp(name
, "threadpoolsize"))
1979 minThreads
= atol(value
);
1982 else if (minThreads
> 100)
1985 else if (!strcasecmp(name
, "timeout"))
1987 timeout
= atol(value
);
1990 else if (timeout
> UCHAR_MAX
)
1991 timeout
= UCHAR_MAX
;
1993 else if (!strcasecmp(name
, "Read"))
1995 if (strchr("Yy", *value
))
1996 cfig
.fileRead
= true;
1998 cfig
.fileRead
= false;
2000 else if (!strcasecmp(name
, "Write"))
2002 if (strchr("Yy", *value
))
2003 cfig
.fileWrite
= true;
2005 cfig
.fileWrite
= false;
2007 else if (!strcasecmp(name
, "Overwrite"))
2009 if (strchr("Yy", *value
))
2010 cfig
.fileOverwrite
= true;
2012 cfig
.fileOverwrite
= false;
2014 else if (!strcasecmp(name
, "port-range"))
2016 char *ptr
= strchr(value
, '-');
2020 cfig
.minport
= atol(value
);
2021 cfig
.maxport
= atol(++ptr
);
2023 if (cfig
.minport
< 1024 || cfig
.minport
>= USHRT_MAX
|| cfig
.maxport
< 1024 || cfig
.maxport
>= USHRT_MAX
|| cfig
.minport
> cfig
.maxport
)
2028 sprintf(logBuff
, "Invalid port range %s", value
);
2029 logMess(logBuff
, 1);
2034 sprintf(logBuff
, "Invalid port range %s", value
);
2035 logMess(logBuff
, 1);
2040 sprintf(logBuff
, "Warning: unknown option %s, ignored", name
);
2041 logMess(logBuff
, 1);
2047 if ((f
= openSection("ALLOWED-CLIENTS", 1, iniFile
)))
2051 while (readSection(raw
, f
))
2057 mySplit(name
, value
, raw
, '-');
2058 rs
= htonl(my_inet_addr(name
));
2061 re
= htonl(my_inet_addr(value
));
2065 if (rs
&& rs
!= INADDR_NONE
&& re
&& re
!= INADDR_NONE
&& rs
<= re
)
2067 cfig
.hostRanges
[i
].rangeStart
= rs
;
2068 cfig
.hostRanges
[i
].rangeEnd
= re
;
2073 sprintf(logBuff
, "Section [ALLOWED-CLIENTS] Invalid entry %s in ini file, ignored", raw
);
2074 logMess(logBuff
, 1);
2082 printf("starting TFTP...\n");
2086 sprintf(logBuff
, "starting TFTP service");
2087 logMess(logBuff
, 1);
2090 for (int i
= 0; i
< MAX_SERVERS
; i
++)
2091 if (cfig
.homes
[i
].target
[0])
2093 sprintf(logBuff
, "alias /%s is mapped to %s", cfig
.homes
[i
].alias
, cfig
.homes
[i
].target
);
2094 logMess(logBuff
, 1);
2097 if (cfig
.hostRanges
[0].rangeStart
)
2101 for (MYWORD i
= 0; i
<= sizeof(cfig
.hostRanges
) && cfig
.hostRanges
[i
].rangeStart
; i
++)
2103 sprintf(logBuff
, "%s", "permitted clients: ");
2104 sprintf(temp
, "%s-", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeStart
)));
2105 strcat(logBuff
, temp
);
2106 sprintf(temp
, "%s", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeEnd
)));
2107 strcat(logBuff
, temp
);
2108 logMess(logBuff
, 1);
2113 sprintf(logBuff
, "%s", "permitted clients: all");
2114 logMess(logBuff
, 1);
2119 sprintf(logBuff
, "server port range: %u-%u", cfig
.minport
, cfig
.maxport
);
2120 logMess(logBuff
, 1);
2124 sprintf(logBuff
, "server port range: all");
2125 logMess(logBuff
, 1);
2128 sprintf(logBuff
, "max blksize: %u", blksize
);
2129 logMess(logBuff
, 1);
2130 sprintf(logBuff
, "default blksize: %u", 512);
2131 logMess(logBuff
, 1);
2132 sprintf(logBuff
, "default timeout: %u", timeout
);
2133 logMess(logBuff
, 1);
2134 sprintf(logBuff
, "file read allowed: %s", cfig
.fileRead
? "Yes" : "No");
2135 logMess(logBuff
, 1);
2136 sprintf(logBuff
, "file create allowed: %s", cfig
.fileWrite
? "Yes" : "No");
2137 logMess(logBuff
, 1);
2138 sprintf(logBuff
, "file overwrite allowed: %s", cfig
.fileOverwrite
? "Yes" : "No");
2139 logMess(logBuff
, 1);
2143 sprintf(logBuff
, "logging: %s", cfig
.logLevel
> 1 ? "all" : "errors");
2144 logMess(logBuff
, 1);
2147 lEvent
= CreateEvent(
2148 NULL
, // default security descriptor
2149 FALSE
, // ManualReset
2151 TEXT("AchalTFTServerLogEvent")); // object name
2155 printf("CreateEvent error: %lu\n", GetLastError());
2158 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2160 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2161 logMess(logBuff
, 0);
2165 tEvent
= CreateEvent(
2166 NULL
, // default security descriptor
2167 FALSE
, // ManualReset
2169 TEXT("AchalTFTServerThreadEvent")); // object name
2173 printf("CreateEvent error: %lu\n", GetLastError());
2176 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2178 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2179 logMess(logBuff
, 0);
2183 sEvent
= CreateEvent(
2184 NULL
, // default security descriptor
2185 FALSE
, // ManualReset
2187 TEXT("AchalTFTServerSocketEvent")); // object name
2191 printf("CreateEvent error: %lu\n", GetLastError());
2194 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2196 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2197 logMess(logBuff
, 0);
2201 cEvent
= CreateEvent(
2202 NULL
, // default security descriptor
2203 FALSE
, // ManualReset
2205 TEXT("AchalTFTServerCountEvent")); // object name
2209 printf("CreateEvent error: %lu\n", GetLastError());
2212 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2214 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2215 logMess(logBuff
, 0);
2221 for (int i
= 0; i
< minThreads
; i
++)
2224 processRequest
, // thread function
2225 0, // default security attributes
2226 NULL
); // argument to thread function
2229 sprintf(logBuff
, "thread pool size: %u", minThreads
);
2230 logMess(logBuff
, 1);
2233 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].port
; i
++)
2235 sprintf(logBuff
, "listening on: %s:%i", IP2String(tempbuff
, network
.tftpConn
[i
].server
), network
.tftpConn
[i
].port
);
2236 logMess(logBuff
, 1);
2241 memset(&newNetwork
, 0, sizeof(data1
));
2243 bool bindfailed
= false;
2245 if ((f
= openSection("LISTEN-ON", 1, iniFile
)))
2249 while (readSection(raw
, f
))
2253 cfig
.ifspecified
= true;
2254 mySplit(name
, value
, raw
, ':');
2263 MYDWORD addr
= my_inet_addr(name
);
2267 newNetwork
.listenServers
[0] = 0;
2268 newNetwork
.listenPorts
[0] = port
;
2272 else if (!findServer(newNetwork
.listenServers
, addr
))
2274 newNetwork
.listenServers
[i
] = addr
;
2275 newNetwork
.listenPorts
[i
] = port
;
2281 sprintf(logBuff
, "Warning: Section [LISTEN-ON], Invalid Interface Address %s, ignored", raw
);
2282 logMess(logBuff
, 1);
2288 if (!cfig
.ifspecified
)
2290 sprintf(logBuff
, "detecting Interfaces..");
2291 logMess(logBuff
, 1);
2292 getInterfaces(&newNetwork
);
2294 for (MYBYTE n
= 0; n
< MAX_SERVERS
&& newNetwork
.staticServers
[n
]; n
++)
2296 newNetwork
.listenServers
[n
] = newNetwork
.staticServers
[n
];
2297 newNetwork
.listenPorts
[n
] = 69;
2303 for (int j
= 0; j
< MAX_SERVERS
&& newNetwork
.listenPorts
[j
]; j
++)
2307 for (; k
< MAX_SERVERS
&& network
.tftpConn
[k
].loaded
; k
++)
2309 if (network
.tftpConn
[k
].ready
&& network
.tftpConn
[k
].server
== newNetwork
.listenServers
[j
] && network
.tftpConn
[k
].port
== newNetwork
.listenPorts
[j
])
2313 if (network
.tftpConn
[k
].ready
&& network
.tftpConn
[k
].server
== newNetwork
.listenServers
[j
] && network
.tftpConn
[k
].port
== newNetwork
.listenPorts
[j
])
2315 memcpy(&(newNetwork
.tftpConn
[i
]), &(network
.tftpConn
[k
]), sizeof(tftpConnType
));
2317 if (newNetwork
.maxFD
< newNetwork
.tftpConn
[i
].sock
)
2318 newNetwork
.maxFD
= newNetwork
.tftpConn
[i
].sock
;
2320 network
.tftpConn
[k
].ready
= false;
2321 //printf("%d, %s found\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2327 newNetwork
.tftpConn
[i
].sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
2329 if (newNetwork
.tftpConn
[i
].sock
== INVALID_SOCKET
)
2332 sprintf(logBuff
, "Failed to Create Socket");
2333 logMess(logBuff
, 1);
2337 //printf("Socket %u\n", newNetwork.tftpConn[i].sock);
2340 newNetwork
.tftpConn
[i
].addr
.sin_family
= AF_INET
;
2341 newNetwork
.tftpConn
[i
].addr
.sin_addr
.s_addr
= newNetwork
.listenServers
[j
];
2342 newNetwork
.tftpConn
[i
].addr
.sin_port
= htons(newNetwork
.listenPorts
[j
]);
2343 int nRet
= bind(newNetwork
.tftpConn
[i
].sock
, (sockaddr
*)&newNetwork
.tftpConn
[i
].addr
, sizeof(struct sockaddr_in
));
2345 if (nRet
== SOCKET_ERROR
|| errno
)
2348 closesocket(newNetwork
.tftpConn
[i
].sock
);
2349 sprintf(logBuff
, "%s Port %i bind failed", IP2String(tempbuff
, newNetwork
.listenServers
[j
]), newNetwork
.listenPorts
[j
]);
2350 logMess(logBuff
, 1);
2354 newNetwork
.tftpConn
[i
].loaded
= true;
2355 newNetwork
.tftpConn
[i
].ready
= true;
2356 newNetwork
.tftpConn
[i
].server
= newNetwork
.listenServers
[j
];
2357 newNetwork
.tftpConn
[i
].port
= newNetwork
.listenPorts
[j
];
2359 //printf("%d, %s created\n", i, IP2String(tempbuff, newNetwork.tftpConn[i].server));
2361 if (newNetwork
.maxFD
< newNetwork
.tftpConn
[i
].sock
)
2362 newNetwork
.maxFD
= newNetwork
.tftpConn
[i
].sock
;
2364 if (!newNetwork
.listenServers
[j
])
2372 cfig
.failureCount
++;
2374 cfig
.failureCount
= 0;
2377 memcpy(&network
, &newNetwork
, sizeof(data1
));
2379 //printf("%i %i %i\n", network.tftpConn[0].ready, network.dnsUdpConn[0].ready, network.dnsTcpConn[0].ready);
2381 if (!network
.tftpConn
[0].ready
)
2383 sprintf(logBuff
, "No Static Interface ready, Waiting...");
2384 logMess(logBuff
, 1);
2388 for (int i
= 0; i
< MAX_SERVERS
&& network
.tftpConn
[i
].loaded
; i
++)
2390 sprintf(logBuff
, "Listening On: %s:%d", IP2String(tempbuff
, network
.tftpConn
[i
].server
), network
.tftpConn
[i
].port
);
2391 logMess(logBuff
, 1);
2394 network
.ready
= true;
2396 } while (detectChange());
2398 //printf("Exiting Init\n");
2406 if (!cfig
.failureCount
)
2408 if (cfig
.ifspecified
)
2412 MYDWORD eventWait
= UINT_MAX
;
2414 if (cfig
.failureCount
)
2415 eventWait
= 10000 * pow(2, cfig
.failureCount
);
2420 overlap
.hEvent
= WSACreateEvent();
2422 ret
= NotifyAddrChange(&hand
, &overlap
);
2424 if (ret
!= NO_ERROR
)
2426 if (WSAGetLastError() != WSA_IO_PENDING
)
2428 printf("NotifyAddrChange error...%d\n", WSAGetLastError());
2433 if ( WaitForSingleObject(overlap
.hEvent
, eventWait
) == WAIT_OBJECT_0
)
2434 WSACloseEvent(overlap
.hEvent
);
2436 network
.ready
= false;
2438 while (network
.busy
)
2441 if (cfig
.failureCount
)
2443 sprintf(logBuff
, "Retrying failed Listening Interfaces..");
2444 logMess(logBuff
, 1);
2448 sprintf(logBuff
, "Network changed, re-detecting Interfaces..");
2449 logMess(logBuff
, 1);
2456 void getInterfaces(data1 *network)
2458 memset(network, 0, sizeof(data1));
2460 SOCKET sd = WSASocket(PF_INET, SOCK_DGRAM, 0, 0, 0, 0);
2462 if (sd == INVALID_SOCKET)
2465 INTERFACE_INFO InterfaceList[MAX_SERVERS];
2466 unsigned long nBytesReturned;
2468 if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
2469 sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
2472 int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
2474 for (int i = 0; i < nNumInterfaces; ++i)
2476 sockaddr_in *pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress);
2477 u_long nFlags = InterfaceList[i].iiFlags;
2479 if (!(nFlags & IFF_POINTTOPOINT))
2481 //printf("%s\n", IP2String(tempbuff, pAddress->sin_addr.S_un.S_addr));
2482 addServer(network->staticServers, pAddress->sin_addr.s_addr);
2491 void getInterfaces(data1
*network
)
2493 memset(network
, 0, sizeof(data1
));
2495 SOCKET sd
= WSASocket(PF_INET
, SOCK_DGRAM
, 0, 0, 0, 0);
2497 if (sd
== INVALID_SOCKET
)
2500 INTERFACE_INFO InterfaceList
[MAX_SERVERS
];
2501 unsigned long nBytesReturned
;
2503 if (WSAIoctl(sd
, SIO_GET_INTERFACE_LIST
, 0, 0, &InterfaceList
,
2504 sizeof(InterfaceList
), &nBytesReturned
, 0, 0) == SOCKET_ERROR
)
2507 int nNumInterfaces
= nBytesReturned
/ sizeof(INTERFACE_INFO
);
2509 for (int i
= 0; i
< nNumInterfaces
; ++i
)
2511 sockaddr_in
*pAddress
= (sockaddr_in
*)&(InterfaceList
[i
].iiAddress
);
2512 u_long nFlags
= InterfaceList
[i
].iiFlags
;
2514 if (pAddress
->sin_addr
.s_addr
)
2516 addServer(network
->allServers
, pAddress
->sin_addr
.s_addr
);
2518 if (!(nFlags
& IFF_POINTTOPOINT
) && (nFlags
& IFF_UP
))
2520 addServer(network
->staticServers
, pAddress
->sin_addr
.s_addr
);
2529 bool addServer(MYDWORD
*array
, MYDWORD ip
)
2531 for (MYBYTE i
= 0; i
< MAX_SERVERS
; i
++)
2533 if (!ip
|| array
[i
] == ip
)
2544 MYDWORD
*findServer(MYDWORD
*array
, MYDWORD ip
)
2548 for (MYBYTE i
= 0; i
< MAX_SERVERS
&& array
[i
]; i
++)
2557 void logMess(char *logBuff
, MYBYTE logLevel
)
2559 WaitForSingleObject(lEvent
, INFINITE
);
2562 printf("%s\n", logBuff
);
2563 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2565 time_t t
= time(NULL
);
2566 tm
*ttm
= localtime(&t
);
2568 if (ttm
->tm_yday
!= loggingDay
)
2570 loggingDay
= ttm
->tm_yday
;
2571 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
2572 fprintf(cfig
.logfile
, "Logging Continued on file %s\n", extbuff
);
2573 fclose(cfig
.logfile
);
2574 cfig
.logfile
= fopen(extbuff
, "at");
2578 fprintf(cfig
.logfile
, "%s\n\n", sVersion
);
2579 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
2580 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
2581 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
2587 strftime(extbuff
, sizeof(extbuff
), "%d-%b-%y %X", ttm
);
2588 fprintf(cfig
.logfile
, "[%s] %s\n", extbuff
, logBuff
);
2589 fflush(cfig
.logfile
);
2594 void logMess(request
*req
, MYBYTE logLevel
)
2596 WaitForSingleObject(lEvent
, INFINITE
);
2602 if (!req
->serverError
.errormessage
[0])
2603 sprintf(req
->serverError
.errormessage
, strerror(errno
));
2606 printf("Client %s:%u %s, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->path
, req
->serverError
.errormessage
);
2608 printf("Client %s:%u, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2610 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2612 time_t t
= time(NULL
);
2613 tm
*ttm
= localtime(&t
);
2615 if (ttm
->tm_yday
!= loggingDay
)
2617 loggingDay
= ttm
->tm_yday
;
2618 strftime(extbuff
, sizeof(extbuff
), logFile
, ttm
);
2619 fprintf(cfig
.logfile
, "Logging Continued on file %s\n", extbuff
);
2620 fclose(cfig
.logfile
);
2621 cfig
.logfile
= fopen(extbuff
, "at");
2625 fprintf(cfig
.logfile
, "%s\n\n", sVersion
);
2626 WritePrivateProfileString("InternetShortcut","URL", extbuff
, lnkFile
);
2627 WritePrivateProfileString("InternetShortcut","IconIndex", "0", lnkFile
);
2628 WritePrivateProfileString("InternetShortcut","IconFile", extbuff
, lnkFile
);
2634 strftime(extbuff
, sizeof(extbuff
), "%d-%b-%y %X", ttm
);
2637 fprintf(cfig
.logfile
, "[%s] Client %s:%u %s, %s\n", extbuff
, IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->path
, req
->serverError
.errormessage
);
2639 fprintf(cfig
.logfile
, "[%s] Client %s:%u, %s\n", extbuff
, IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2641 fflush(cfig
.logfile
);