1 /**************************************************************************
2 * Copyright (C) 2005 by Achal Dhir *
3 * achaldhir@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
33 char serviceName
[] = "TFTPServer";
34 char displayName
[] = "TFTP Server Multithreaded";
35 char sVersion
[] = "TFTP Server MultiThreaded Version 1.61 Windows Built 1611";
36 char iniFile
[_MAX_PATH
];
37 char logFile
[_MAX_PATH
];
41 char notFileSep
= '/';
46 //ThreadPool Variables
51 BYTE currentServer
= UCHAR_MAX
;
57 SERVICE_STATUS serviceStatus
;
58 SERVICE_STATUS_HANDLE serviceStatusHandle
= 0;
59 HANDLE stopServiceEvent
= 0;
61 void WINAPI
ServiceControlHandler(DWORD controlCode
)
65 case SERVICE_CONTROL_INTERROGATE
:
68 case SERVICE_CONTROL_SHUTDOWN
:
69 case SERVICE_CONTROL_STOP
:
70 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
71 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
73 SetEvent(stopServiceEvent
);
76 case SERVICE_CONTROL_PAUSE
:
79 case SERVICE_CONTROL_CONTINUE
:
83 if (controlCode
>= 128 && controlCode
<= 255)
89 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
92 void WINAPI
ServiceMain(DWORD
/*argc*/, TCHAR
* /*argv*/[])
94 serviceStatus
.dwServiceType
= SERVICE_WIN32
;
95 serviceStatus
.dwCurrentState
= SERVICE_STOPPED
;
96 serviceStatus
.dwControlsAccepted
= 0;
97 serviceStatus
.dwWin32ExitCode
= NO_ERROR
;
98 serviceStatus
.dwServiceSpecificExitCode
= NO_ERROR
;
99 serviceStatus
.dwCheckPoint
= 0;
100 serviceStatus
.dwWaitHint
= 0;
102 serviceStatusHandle
= RegisterServiceCtrlHandler(serviceName
, ServiceControlHandler
);
104 if (serviceStatusHandle
)
106 serviceStatus
.dwCurrentState
= SERVICE_START_PENDING
;
107 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
117 stopServiceEvent
= CreateEvent(0, FALSE
, FALSE
, 0);
119 serviceStatus
.dwControlsAccepted
|= (SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
120 serviceStatus
.dwCurrentState
= SERVICE_RUNNING
;
121 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
127 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
128 FD_SET(cfig
.tftpConn
[i
].sock
, &readfds
);
130 int fdsReady
= select(cfig
.maxFD
, &readfds
, NULL
, NULL
, &tv
);
132 for (int i
= 0; fdsReady
> 0 && i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
134 if (FD_ISSET(cfig
.tftpConn
[i
].sock
, &readfds
))
136 WaitForSingleObject(sEvent
, INFINITE
);
140 if (!totalThreads
|| activeThreads
>= totalThreads
)
143 processRequest
, // thread function
144 0, // default security attributes
145 NULL
); // argument to thread function
150 WaitForSingleObject(sEvent
, INFINITE
);
156 while (WaitForSingleObject(stopServiceEvent
, 0) == WAIT_TIMEOUT
);
159 fclose(cfig
.logfile
);
161 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
162 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
164 sprintf(logBuff
, "Closing Network Connections...");
167 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
168 closesocket(cfig
.tftpConn
[i
].sock
);
172 sprintf(logBuff
, "TFTP Server Stopped !");
175 serviceStatus
.dwControlsAccepted
&= ~(SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
176 serviceStatus
.dwCurrentState
= SERVICE_STOPPED
;
177 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
178 CloseHandle(stopServiceEvent
);
179 stopServiceEvent
= 0;
185 SERVICE_TABLE_ENTRY serviceTable
[] =
187 {serviceName
, ServiceMain
},
191 StartServiceCtrlDispatcher(serviceTable
);
194 bool stopService(SC_HANDLE service
)
198 SERVICE_STATUS serviceStatus
;
199 QueryServiceStatus(service
, &serviceStatus
);
200 if (serviceStatus
.dwCurrentState
!= SERVICE_STOPPED
)
202 ControlService(service
, SERVICE_CONTROL_STOP
, &serviceStatus
);
203 printf("Stopping Service.");
204 for (int i
= 0; i
< 100; i
++)
206 QueryServiceStatus(service
, &serviceStatus
);
207 if (serviceStatus
.dwCurrentState
== SERVICE_STOPPED
)
225 void installService()
227 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE
);
229 if (serviceControlManager
)
231 SC_HANDLE service
= OpenService(serviceControlManager
,
232 serviceName
, SERVICE_QUERY_STATUS
);
235 printf("Service Already Exists..\n");
236 StartService(service
,0,NULL
);
237 CloseServiceHandle(service
);
241 TCHAR path
[ _MAX_PATH
+ 1 ];
242 if (GetModuleFileName(0, path
, sizeof(path
) / sizeof(path
[0])) > 0)
244 SC_HANDLE service
= CreateService(serviceControlManager
,
245 serviceName
, displayName
,
246 SERVICE_ALL_ACCESS
, SERVICE_WIN32_OWN_PROCESS
,
247 SERVICE_AUTO_START
, SERVICE_ERROR_IGNORE
, path
,
251 printf("Successfully installed.. !\n");
252 StartService(service
,0,NULL
);
253 CloseServiceHandle(service
);
256 printf("Installation Failed..\n");
259 CloseServiceHandle(serviceControlManager
);
265 void uninstallService()
267 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
269 if (serviceControlManager
)
271 SC_HANDLE service
= OpenService(serviceControlManager
,
272 serviceName
, SERVICE_QUERY_STATUS
| SERVICE_STOP
| DELETE
);
275 if (stopService(service
))
277 DeleteService(service
);
278 printf("Successfully Removed !\n");
281 printf("Failed to Stop Service..\n");
283 CloseServiceHandle(service
);
286 CloseServiceHandle(serviceControlManager
);
292 void printWindowsError()
294 DWORD dw
= GetLastError();
301 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
302 FORMAT_MESSAGE_FROM_SYSTEM
|
303 FORMAT_MESSAGE_IGNORE_INSERTS
,
306 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
310 _tprintf(_T("Error: %s\nPress Enter..\n"), (LPTSTR
)lpMsgBuf
);
318 int main(int argc
, TCHAR
* argv
[])
321 osvi
.dwOSVersionInfoSize
= sizeof(osvi
);
322 bool result
= GetVersionEx(&osvi
);
324 if (result
&& osvi
.dwPlatformId
>= VER_PLATFORM_WIN32_NT
)
326 if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-i")) == 0)
328 else if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-u")) == 0)
330 else if (argc
> 1 && lstrcmpi(argv
[1], TEXT("-v")) == 0)
332 SC_HANDLE serviceControlManager
= OpenSCManager(0, 0, SC_MANAGER_CONNECT
);
333 bool serviceStopped
= true;
335 if (serviceControlManager
)
337 SC_HANDLE service
= OpenService(serviceControlManager
,
338 serviceName
, SERVICE_QUERY_STATUS
| SERVICE_STOP
);
341 serviceStopped
= stopService(service
);
342 CloseServiceHandle(service
);
344 CloseServiceHandle(serviceControlManager
);
352 printf("Failed to Stop Service\n");
357 else if (argc
== 1 || lstrcmpi(argv
[1], TEXT("-v")) == 0)
360 printf("This option is not available on Windows95/98/ME\n");
375 printf("\naccepting requests..\n");
379 //printf("Active=%u Total=%u\n",activeThreads, totalThreads);
383 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
384 FD_SET(cfig
.tftpConn
[i
].sock
, &readfds
);
386 fdsReady
= select(cfig
.maxFD
, &readfds
, NULL
, NULL
, &tv
);
389 // printf("%s\n", strerror(errno));
391 for (int i
= 0; fdsReady
> 0 && i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
393 if (FD_ISSET(cfig
.tftpConn
[i
].sock
, &readfds
))
395 //printf("Request Waiting\n");
397 WaitForSingleObject(sEvent
, INFINITE
);
401 if (!totalThreads
|| activeThreads
>= totalThreads
)
404 processRequest
, // thread function
405 0, // default security attributes
406 NULL
); // argument to thread function
410 //printf("thread signalled=%u\n",SetEvent(tEvent));
412 WaitForSingleObject(sEvent
, INFINITE
);
420 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
421 closesocket(cfig
.tftpConn
[i
].sock
);
426 void processRequest(void *lpParam
)
428 //printf("New Thread %u\n",GetCurrentThreadId());
432 WaitForSingleObject(cEvent
, INFINITE
);
438 WaitForSingleObject(tEvent
, INFINITE
);
439 //printf("In Thread %u\n",GetCurrentThreadId());
441 WaitForSingleObject(cEvent
, INFINITE
);
445 if (currentServer
>= MAX_SERVERS
|| !cfig
.tftpConn
[currentServer
].port
)
448 req
.attempt
= UCHAR_MAX
;
452 memset(&req
, 0, sizeof(request
));
453 req
.sock
= INVALID_SOCKET
;
455 req
.clientsize
= sizeof(req
.client
);
456 req
.sockInd
= currentServer
;
457 currentServer
= UCHAR_MAX
;
458 req
.knock
= cfig
.tftpConn
[req
.sockInd
].sock
;
460 if (req
.knock
== INVALID_SOCKET
)
463 req
.attempt
= UCHAR_MAX
;
468 req
.bytesRecd
= recvfrom(req
.knock
, (char*)&req
.mesin
, sizeof(message
), 0, (sockaddr
*)&req
.client
, &req
.clientsize
);
469 errno
= WSAGetLastError();
471 //printf("socket Signalled=%u\n",SetEvent(sEvent));
474 if (!errno
&& req
.bytesRecd
> 0)
476 if (cfig
.hostRanges
[0].rangeStart
)
478 DWORD iip
= ntohl(req
.client
.sin_addr
.s_addr
);
479 bool allowed
= false;
481 for (int j
= 0; j
<= 32 && cfig
.hostRanges
[j
].rangeStart
; j
++)
483 if (iip
>= cfig
.hostRanges
[j
].rangeStart
&& iip
<= cfig
.hostRanges
[j
].rangeEnd
)
492 req
.serverError
.opcode
= htons(5);
493 req
.serverError
.errorcode
= htons(2);
494 strcpy(req
.serverError
.errormessage
, "Access Denied");
496 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
497 req
.attempt
= UCHAR_MAX
;
502 if ((htons(req
.mesin
.opcode
) == 5))
504 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.clientError
.errorcode
), req
.clientError
.errormessage
);
506 req
.attempt
= UCHAR_MAX
;
509 else if (htons(req
.mesin
.opcode
) != 1 && htons(req
.mesin
.opcode
) != 2)
511 req
.serverError
.opcode
= htons(5);
512 req
.serverError
.errorcode
= htons(5);
513 sprintf(req
.serverError
.errormessage
, "Unknown Transfer Id");
515 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
516 req
.attempt
= UCHAR_MAX
;
522 sprintf(req
.serverError
.errormessage
, "Communication Error");
524 req
.attempt
= UCHAR_MAX
;
529 req
.timeout
= timeout
;
530 req
.expiry
= time(NULL
) + req
.timeout
;
531 bool fetchAck
= false;
533 req
.sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
535 if (req
.sock
== INVALID_SOCKET
)
537 req
.serverError
.opcode
= htons(5);
538 req
.serverError
.errorcode
= htons(0);
539 strcpy(req
.serverError
.errormessage
, "Thread Socket Creation Error");
540 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
542 req
.attempt
= UCHAR_MAX
;
547 service
.sin_family
= AF_INET
;
548 service
.sin_addr
.s_addr
= cfig
.tftpConn
[req
.sockInd
].server
;
552 for (WORD comport
= cfig
.minport
; ; comport
++)
554 service
.sin_port
= htons(comport
);
556 if (comport
> cfig
.maxport
)
558 req
.serverError
.opcode
= htons(5);
559 req
.serverError
.errorcode
= htons(0);
560 strcpy(req
.serverError
.errormessage
, "No port is free");
561 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
563 req
.attempt
= UCHAR_MAX
;
566 else if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
574 service
.sin_port
= 0;
576 if (bind(req
.sock
, (sockaddr
*) &service
, sizeof(service
)) == -1)
578 strcpy(req
.serverError
.errormessage
, "Thread failed to bind");
579 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
581 req
.attempt
= UCHAR_MAX
;
585 if (req
.attempt
>= 3)
588 if (connect(req
.sock
, (sockaddr
*)&req
.client
, req
.clientsize
) == -1)
590 req
.serverError
.opcode
= htons(5);
591 req
.serverError
.errorcode
= htons(0);
592 strcpy(req
.serverError
.errormessage
, "Connect Failed");
593 sendto(req
.knock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0, (sockaddr
*)&req
.client
, req
.clientsize
);
595 req
.attempt
= UCHAR_MAX
;
599 //sprintf(req.serverError.errormessage, "In Temp, Socket");
602 char *inPtr
= req
.mesin
.buffer
;
603 *(inPtr
+ (req
.bytesRecd
- 3)) = 0;
604 req
.filename
= inPtr
;
606 if (!strlen(req
.filename
) || strlen(req
.filename
) > UCHAR_MAX
)
608 req
.serverError
.opcode
= htons(5);
609 req
.serverError
.errorcode
= htons(4);
610 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Filename");
611 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
612 req
.attempt
= UCHAR_MAX
;
617 inPtr
+= strlen(inPtr
) + 1;
620 if (!strlen(req
.mode
) || strlen(req
.mode
) > 25)
622 req
.serverError
.opcode
= htons(5);
623 req
.serverError
.errorcode
= htons(4);
624 strcpy(req
.serverError
.errormessage
, "Malformed Request, Invalid/Missing Mode");
625 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
626 req
.attempt
= UCHAR_MAX
;
631 inPtr
+= strlen(inPtr
) + 1;
633 for (DWORD i
= 0; i
< strlen(req
.filename
); i
++)
634 if (req
.filename
[i
] == notFileSep
)
635 req
.filename
[i
] = fileSep
;
639 tempbuff
[2] = fileSep
;
642 if (strstr(req
.filename
, tempbuff
))
644 req
.serverError
.opcode
= htons(5);
645 req
.serverError
.errorcode
= htons(2);
646 strcpy(req
.serverError
.errormessage
, "Access violation");
647 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
649 req
.attempt
= UCHAR_MAX
;
653 if (req
.filename
[0] == fileSep
)
656 if (!cfig
.homes
[0].alias
[0])
658 if (strlen(cfig
.homes
[0].target
) + strlen(req
.filename
) >= sizeof(req
.path
))
660 req
.serverError
.opcode
= htons(5);
661 req
.serverError
.errorcode
= htons(4);
662 sprintf(req
.serverError
.errormessage
, "Filename too large");
663 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
665 req
.attempt
= UCHAR_MAX
;
669 strcpy(req
.path
, cfig
.homes
[0].target
);
670 strcat(req
.path
, req
.filename
);
674 char *bname
= strchr(req
.filename
, fileSep
);
683 req
.serverError
.opcode
= htons(5);
684 req
.serverError
.errorcode
= htons(2);
685 sprintf(req
.serverError
.errormessage
, "Missing directory/alias");
686 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
688 req
.attempt
= UCHAR_MAX
;
692 for (int i
= 0; i
< 8; i
++)
694 //printf("%s=%i\n", req.filename, cfig.homes[i].alias[0]);
695 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(req
.filename
, cfig
.homes
[i
].alias
))
697 if (strlen(cfig
.homes
[i
].target
) + strlen(bname
) >= sizeof(req
.path
))
699 req
.serverError
.opcode
= htons(5);
700 req
.serverError
.errorcode
= htons(4);
701 sprintf(req
.serverError
.errormessage
, "Filename too large");
702 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
704 req
.attempt
= UCHAR_MAX
;
708 strcpy(req
.path
, cfig
.homes
[i
].target
);
709 strcat(req
.path
, bname
);
712 else if (i
== 7 || !cfig
.homes
[i
].alias
[0])
714 req
.serverError
.opcode
= htons(5);
715 req
.serverError
.errorcode
= htons(2);
716 sprintf(req
.serverError
.errormessage
, "No such directory/alias %s", req
.filename
);
717 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
719 req
.attempt
= UCHAR_MAX
;
725 if (req
.attempt
>= 3)
728 if (ntohs(req
.mesin
.opcode
) == 1)
732 req
.serverError
.opcode
= htons(5);
733 req
.serverError
.errorcode
= htons(2);
734 strcpy(req
.serverError
.errormessage
, "GET Access Denied");
736 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
737 req
.attempt
= UCHAR_MAX
;
747 if (!strcasecmp(tmp
, "blksize"))
749 tmp
+= strlen(tmp
) + 1;
750 DWORD val
= atol(tmp
);
754 else if (val
> blksize
)
761 tmp
+= strlen(tmp
) + 1;
767 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
768 req
.file
= fopen(req
.path
, "rt");
770 req
.file
= fopen(req
.path
, "rb");
772 if (errno
|| !req
.file
)
774 req
.serverError
.opcode
= htons(5);
775 req
.serverError
.errorcode
= htons(1);
776 strcpy(req
.serverError
.errormessage
, "File not found or No Access");
778 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
779 req
.attempt
= UCHAR_MAX
;
783 setvbuf(req
.file
, NULL
, _IOFBF
, req
.blksize
);
787 if (!cfig
.fileWrite
&& !cfig
.fileOverwrite
)
789 req
.serverError
.opcode
= htons(5);
790 req
.serverError
.errorcode
= htons(2);
791 strcpy(req
.serverError
.errormessage
, "PUT Access Denied");
792 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
794 req
.attempt
= UCHAR_MAX
;
798 req
.file
= fopen(req
.path
, "rb");
805 if (!cfig
.fileOverwrite
)
807 req
.serverError
.opcode
= htons(5);
808 req
.serverError
.errorcode
= htons(6);
809 strcpy(req
.serverError
.errormessage
, "File already exists");
810 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
812 req
.attempt
= UCHAR_MAX
;
816 else if (!cfig
.fileWrite
)
818 req
.serverError
.opcode
= htons(5);
819 req
.serverError
.errorcode
= htons(2);
820 strcpy(req
.serverError
.errormessage
, "Create File Access Denied");
821 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
823 req
.attempt
= UCHAR_MAX
;
829 if (!strcasecmp(req
.mode
, "netascii") || !strcasecmp(req
.mode
, "ascii"))
830 req
.file
= fopen(req
.path
, "wt");
832 req
.file
= fopen(req
.path
, "wb");
834 if (errno
|| !req
.file
)
836 req
.serverError
.opcode
= htons(5);
837 req
.serverError
.errorcode
= htons(2);
838 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
839 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
841 req
.attempt
= UCHAR_MAX
;
849 char *outPtr
= req
.mesout
.buffer
;
850 req
.mesout
.opcode
= htons(6);
854 //printf("%s\n", inPtr);
855 if (!strcasecmp(inPtr
, "blksize"))
857 strcpy(outPtr
, inPtr
);
858 outPtr
+= strlen(outPtr
) + 1;
859 inPtr
+= strlen(inPtr
) + 1;
864 else if (val
> blksize
)
868 sprintf(outPtr
, "%lu", val
);
869 outPtr
+= strlen(outPtr
) + 1;
871 else if (!strcasecmp(inPtr
, "tsize"))
873 strcpy(outPtr
, inPtr
);
874 outPtr
+= strlen(outPtr
) + 1;
875 inPtr
+= strlen(inPtr
) + 1;
877 if (ntohs(req
.mesin
.opcode
) == 1)
879 if (!fseek(req
.file
, 0, SEEK_END
))
881 if (ftell(req
.file
) >= 0)
883 req
.tsize
= ftell(req
.file
);
884 sprintf(outPtr
, "%lu", req
.tsize
);
885 outPtr
+= strlen(outPtr
) + 1;
889 req
.serverError
.opcode
= htons(5);
890 req
.serverError
.errorcode
= htons(2);
891 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
892 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
894 req
.attempt
= UCHAR_MAX
;
900 req
.serverError
.opcode
= htons(5);
901 req
.serverError
.errorcode
= htons(2);
902 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
903 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
905 req
.attempt
= UCHAR_MAX
;
912 sprintf(outPtr
, "%lu", req
.tsize
);
913 outPtr
+= strlen(outPtr
) + 1;
916 else if (!strcasecmp(inPtr
, "timeout"))
918 strcpy(outPtr
, inPtr
);
919 outPtr
+= strlen(outPtr
) + 1;
920 inPtr
+= strlen(inPtr
) + 1;
925 else if (val
> UCHAR_MAX
)
929 req
.expiry
= time(NULL
) + req
.timeout
;
930 sprintf(outPtr
, "%lu", val
);
931 outPtr
+= strlen(outPtr
) + 1;
934 inPtr
+= strlen(inPtr
) + 1;
935 //printf("=%u\n", val);
938 if (req
.attempt
>= 3)
942 req
.bytesReady
= (DWORD_PTR
)outPtr
- (DWORD_PTR
)&req
.mesout
;
943 //printf("Bytes Ready=%u\n", req.bytesReady);
944 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
945 errno
= WSAGetLastError();
947 else if (htons(req
.mesin
.opcode
) == 2)
949 req
.acout
.opcode
= htons(4);
950 req
.acout
.block
= htons(0);
953 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
954 errno
= WSAGetLastError();
959 sprintf(req
.serverError
.errormessage
, "Communication Error");
961 req
.attempt
= UCHAR_MAX
;
964 else if (ntohs(req
.mesin
.opcode
) == 1)
967 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
968 req
.pkt
[1] = (packet
*)calloc(1, req
.blksize
+ 4);
970 if (errno
|| !req
.pkt
[0] || !req
.pkt
[1])
972 sprintf(req
.serverError
.errormessage
, "Memory Error");
974 req
.attempt
= UCHAR_MAX
;
978 long ftellLoc
= ftell(req
.file
);
982 if (fseek(req
.file
, 0, SEEK_SET
))
984 req
.serverError
.opcode
= htons(5);
985 req
.serverError
.errorcode
= htons(2);
986 strcpy(req
.serverError
.errormessage
, "File Access Error");
987 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
989 req
.attempt
= UCHAR_MAX
;
993 else if (ftellLoc
< 0)
995 req
.serverError
.opcode
= htons(5);
996 req
.serverError
.errorcode
= htons(2);
997 strcpy(req
.serverError
.errormessage
, "File Access Error");
998 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1000 req
.attempt
= UCHAR_MAX
;
1005 req
.pkt
[0]->opcode
= htons(3);
1006 req
.pkt
[0]->block
= htons(1);
1007 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1011 req
.serverError
.opcode
= htons(5);
1012 req
.serverError
.errorcode
= htons(2);
1013 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1014 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1016 req
.attempt
= UCHAR_MAX
;
1020 if (req
.bytesRead
[0] == req
.blksize
)
1022 req
.pkt
[1]->opcode
= htons(3);
1023 req
.pkt
[1]->block
= htons(2);
1024 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1025 if (req
.bytesRead
[1] < req
.blksize
)
1039 req
.serverError
.opcode
= htons(5);
1040 req
.serverError
.errorcode
= htons(2);
1041 strcpy(req
.serverError
.errormessage
, "Invalid Path or No Access");
1042 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1044 req
.attempt
= UCHAR_MAX
;
1048 while (req
.attempt
<= 3)
1052 FD_ZERO(&req
.readfds
);
1055 FD_SET(req
.sock
, &req
.readfds
);
1056 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1058 if (FD_ISSET(req
.sock
, &req
.readfds
))
1061 req
.bytesRecd
= recv(req
.sock
, (char*)&req
.mesin
, sizeof(message
), 0);
1062 errno
= WSAGetLastError();
1063 if (req
.bytesRecd
<= 0 || errno
)
1065 sprintf(req
.serverError
.errormessage
, "Communication Error");
1067 req
.attempt
= UCHAR_MAX
;
1070 else if(req
.bytesRecd
>= 4 && ntohs(req
.mesin
.opcode
) == 4)
1072 if (ntohs(req
.acin
.block
) == req
.block
)
1078 else if (req
.expiry
> time(NULL
))
1083 else if (ntohs(req
.mesin
.opcode
) == 5)
1085 sprintf(req
.serverError
.errormessage
, "Client %s:%u, Error Code %i at Client, %s", inet_ntoa(req
.client
.sin_addr
), ntohs(req
.client
.sin_port
), ntohs(req
.clientError
.errorcode
), req
.clientError
.errormessage
);
1087 req
.attempt
= UCHAR_MAX
;
1092 req
.serverError
.opcode
= htons(5);
1093 req
.serverError
.errorcode
= htons(4);
1094 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.mesin
.opcode
));
1095 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1097 req
.attempt
= UCHAR_MAX
;
1101 else if (req
.expiry
> time(NULL
))
1114 if (req
.attempt
>= 3)
1116 req
.serverError
.opcode
= htons(5);
1117 req
.serverError
.errorcode
= htons(0);
1119 if (req
.fblock
&& !req
.block
)
1120 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1122 strcpy(req
.serverError
.errormessage
, "Timeout");
1125 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1126 req
.attempt
= UCHAR_MAX
;
1129 else if (!req
.fblock
)
1132 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1133 errno
= WSAGetLastError();
1136 sprintf(req
.serverError
.errormessage
, "Communication Error");
1138 req
.attempt
= UCHAR_MAX
;
1141 req
.expiry
= time(NULL
) + req
.timeout
;
1143 else if (ntohs(req
.pkt
[0]->block
) == req
.block
)
1146 send(req
.sock
, (const char*)req
.pkt
[0], req
.bytesRead
[0] + 4, 0);
1147 errno
= WSAGetLastError();
1150 sprintf(req
.serverError
.errormessage
, "Communication Error");
1152 req
.attempt
= UCHAR_MAX
;
1155 req
.expiry
= time(NULL
) + req
.timeout
;
1159 req
.tblock
= ntohs(req
.pkt
[1]->block
) + 1;
1160 if (req
.tblock
== req
.block
)
1162 req
.pkt
[1]->block
= htons(++req
.tblock
);
1163 req
.bytesRead
[1] = fread(&req
.pkt
[1]->buffer
, 1, req
.blksize
, req
.file
);
1167 req
.serverError
.opcode
= htons(5);
1168 req
.serverError
.errorcode
= htons(4);
1169 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1170 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1172 req
.attempt
= UCHAR_MAX
;
1175 else if (req
.bytesRead
[1] < req
.blksize
)
1183 else if (ntohs(req
.pkt
[1]->block
) == req
.block
)
1186 send(req
.sock
, (const char*)req
.pkt
[1], req
.bytesRead
[1] + 4, 0);
1187 errno
= WSAGetLastError();
1190 sprintf(req
.serverError
.errormessage
, "Communication Error");
1192 req
.attempt
= UCHAR_MAX
;
1196 req
.expiry
= time(NULL
) + req
.timeout
;
1200 req
.tblock
= ntohs(req
.pkt
[0]->block
) + 1;
1201 if (req
.tblock
== req
.block
)
1203 req
.pkt
[0]->block
= htons(++req
.tblock
);
1204 req
.bytesRead
[0] = fread(&req
.pkt
[0]->buffer
, 1, req
.blksize
, req
.file
);
1207 req
.serverError
.opcode
= htons(5);
1208 req
.serverError
.errorcode
= htons(4);
1209 sprintf(req
.serverError
.errormessage
, strerror(errno
));
1210 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1212 req
.attempt
= UCHAR_MAX
;
1215 else if (req
.bytesRead
[0] < req
.blksize
)
1225 sprintf(req
.serverError
.errormessage
, "%lu Blocks Served", req
.fblock
- 1);
1227 req
.attempt
= UCHAR_MAX
;
1232 else if (ntohs(req
.mesin
.opcode
) == 2)
1235 req
.pkt
[0] = (packet
*)calloc(1, req
.blksize
+ 4);
1237 if (errno
|| !req
.pkt
[0])
1239 sprintf(req
.serverError
.errormessage
, "Memory Error");
1241 req
.attempt
= UCHAR_MAX
;
1245 while (req
.attempt
<= 3)
1247 FD_ZERO(&req
.readfds
);
1250 FD_SET(req
.sock
, &req
.readfds
);
1251 select(req
.sock
+ 1, &req
.readfds
, NULL
, NULL
, &req
.tv
);
1253 if (FD_ISSET(req
.sock
, &req
.readfds
))
1256 req
.bytesRecd
= recv(req
.sock
, (char*)req
.pkt
[0], req
.blksize
+ 4, 0);
1257 errno
= WSAGetLastError();
1261 sprintf(req
.serverError
.errormessage
, "Communication Error");
1263 req
.attempt
= UCHAR_MAX
;
1270 if (req
.bytesRecd
>= 4)
1272 if (ntohs(req
.pkt
[0]->opcode
) == 3)
1274 req
.tblock
= req
.block
+ 1;
1276 if (ntohs(req
.pkt
[0]->block
) == req
.tblock
)
1278 req
.acout
.opcode
= htons(4);
1279 req
.acout
.block
= req
.pkt
[0]->block
;
1283 req
.expiry
= time(NULL
) + req
.timeout
;
1286 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1287 errno
= WSAGetLastError();
1291 sprintf(req
.serverError
.errormessage
, "Communication Error");
1293 req
.attempt
= UCHAR_MAX
;
1297 if (req
.bytesRecd
> 4)
1300 if (fwrite(&req
.pkt
[0]->buffer
, req
.bytesRecd
- 4, 1, req
.file
) != 1 || errno
)
1302 req
.serverError
.opcode
= htons(5);
1303 req
.serverError
.errorcode
= htons(3);
1304 strcpy(req
.serverError
.errormessage
, "Disk full or allocation exceeded");
1305 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1307 req
.attempt
= UCHAR_MAX
;
1316 if ((WORD
)req
.bytesRecd
< req
.blksize
+ 4)
1320 sprintf(req
.serverError
.errormessage
, "%lu Blocks Received", req
.fblock
);
1322 req
.attempt
= UCHAR_MAX
;
1326 else if (req
.expiry
> time(NULL
))
1328 else if (req
.attempt
>= 3)
1330 req
.serverError
.opcode
= htons(5);
1331 req
.serverError
.errorcode
= htons(0);
1333 if (req
.fblock
&& !req
.block
)
1334 strcpy(req
.serverError
.errormessage
, "Large File, Block# Rollover not supported by Client");
1336 strcpy(req
.serverError
.errormessage
, "Timeout");
1339 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1340 req
.attempt
= UCHAR_MAX
;
1345 req
.expiry
= time(NULL
) + req
.timeout
;
1347 send(req
.sock
, (const char*)&req
.mesout
, req
.bytesReady
, 0);
1348 errno
= WSAGetLastError();
1353 sprintf(req
.serverError
.errormessage
, "Communication Error");
1355 req
.attempt
= UCHAR_MAX
;
1360 else if (req
.bytesRecd
> (int)sizeof(message
))
1362 req
.serverError
.opcode
= htons(5);
1363 req
.serverError
.errorcode
= htons(4);
1364 sprintf(req
.serverError
.errormessage
, "Error: Incoming Packet too large");
1365 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
1367 req
.attempt
= UCHAR_MAX
;
1370 else if (ntohs(req
.pkt
[0]->opcode
) == 5)
1372 sprintf(req
.serverError
.errormessage
, "Error Code %i at Client, %s", ntohs(req
.pkt
[0]->block
), &req
.pkt
[0]->buffer
);
1374 req
.attempt
= UCHAR_MAX
;
1379 req
.serverError
.opcode
= htons(5);
1380 req
.serverError
.errorcode
= htons(4);
1381 sprintf(req
.serverError
.errormessage
, "Unexpected Option Code %i", ntohs(req
.pkt
[0]->opcode
));
1382 send(req
.sock
, (const char*)&req
.serverError
, strlen(req
.serverError
.errormessage
) + 5, 0);
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
;
1424 while (cleanReq(&req
));
1426 WaitForSingleObject(cEvent
, INFINITE
);
1430 //printf("Thread %u Killed\n",GetCurrentThreadId());
1435 bool cleanReq(request
* req
)
1437 //printf("cleaning\n");
1442 if (!(req
->sock
== INVALID_SOCKET
))
1445 closesocket(req
->sock
);
1454 WaitForSingleObject(cEvent
, INFINITE
);
1458 //printf("cleaned\n");
1460 return (totalThreads
<= minThreads
);
1463 char* myGetToken(char* buff
, BYTE index
)
1472 buff
+= strlen(buff
) + 1;
1478 WORD
myTokenize(char *target
, char *source
, char *sep
, bool whiteSep
)
1486 if (sep
&& sep
[0] && strchr(sep
, (*source
)))
1492 else if (whiteSep
&& *source
<= 32)
1519 //printf("%s\n", target);
1524 char* myTrim(char *target
, char *source
)
1526 while ((*source
) && (*source
) <= 32)
1531 for (; i
< 511 && source
[i
]; i
++)
1532 target
[i
] = source
[i
];
1534 target
[i
] = source
[i
];
1537 for (; i
>= 0 && target
[i
] <= 32; i
--)
1543 void mySplit(char *name
, char *value
, char *source
, char splitChar
)
1549 for (; source
[i
] && j
<= 510 && source
[i
] != splitChar
; i
++, j
++)
1551 name
[j
] = source
[i
];
1557 for (; k
<= 510 && source
[i
]; i
++, k
++)
1559 value
[k
] = source
[i
];
1567 myTrim(value
, value
);
1568 //printf("%s %s\n", name, value);
1571 bool getSection(const char *sectionName
, char *buffer
, BYTE serial
, char *fileName
)
1573 //printf("%s=%s\n",fileName,sectionName);
1575 sprintf(section
, "[%s]", sectionName
);
1577 FILE *f
= fopen(fileName
, "rt");
1583 while (fgets(buff
, 511, f
))
1588 if (strstr(buff
, section
) == buff
)
1591 if (found
== serial
)
1593 //printf("%s=%s\n",fileName,sectionName);
1594 while (fgets(buff
, 511, f
))
1598 if (strstr(buff
, "[") == buff
)
1601 if (((*buff
) >= '0' && (*buff
) <= '9') || ((*buff
) >= 'A' && (*buff
) <= 'Z') || ((*buff
) >= 'a' && (*buff
) <= 'z') || (((*buff
) && strchr("/\\?*", (*buff
)))))
1603 buffer
+= sprintf(buffer
, "%s", buff
);
1616 return (found
== serial
);
1619 char *IP2String(char *target
, DWORD ip
)
1623 sprintf(target
, "%u.%u.%u.%u", inaddr
.octate
[0], inaddr
.octate
[1], inaddr
.octate
[2], inaddr
.octate
[3]);
1627 bool isIP(char *string
)
1631 for (; *string
; string
++)
1633 if (*string
== '.' && *(string
+ 1) != '.')
1635 else if (*string
< '0' || *string
> '9')
1645 char *myUpper(char *string
)
1647 char diff
= 'a' - 'A';
1648 WORD len
= strlen(string
);
1649 for (int i
= 0; i
< len
; i
++)
1650 if (string
[i
] >= 'a' && string
[i
] <= 'z')
1655 char *myLower(char *string
)
1657 char diff
= 'a' - 'A';
1658 WORD len
= strlen(string
);
1659 for (int i
= 0; i
< len
; i
++)
1660 if (string
[i
] >= 'A' && string
[i
] <= 'Z')
1667 memset(&cfig
, 0, sizeof(cfig
));
1669 GetModuleFileName(NULL
, iniFile
, MAX_PATH
);
1670 char *iniFileExt
= strrchr(iniFile
, '.');
1671 strcpy(iniFileExt
, ".ini");
1672 GetModuleFileName(NULL
, logFile
, MAX_PATH
);
1673 iniFileExt
= strrchr(logFile
, '.');
1674 strcpy(iniFileExt
, ".log");
1683 printf("%s\n\n", sVersion
);
1685 else if (getSection("LOGGING", iniStr
, 1, iniFile
))
1687 char *iniStrPtr
= myGetToken(iniStr
, 0);
1689 if (!iniStrPtr
[0] || !strcasecmp(iniStrPtr
, "None"))
1691 else if (!strcasecmp(iniStrPtr
, "Errors"))
1693 else if (!strcasecmp(iniStrPtr
, "All"))
1695 else if (!strcasecmp(iniStrPtr
, "Debug"))
1698 cfig
.logLevel
= UCHAR_MAX
;
1701 if (!verbatim
&& cfig
.logLevel
)
1703 cfig
.logfile
= fopen(logFile
, "wt");
1707 fclose(cfig
.logfile
);
1708 cfig
.logfile
= fopen(logFile
, "at");
1709 fprintf(cfig
.logfile
, "%s\n", sVersion
);
1713 if (cfig
.logLevel
== UCHAR_MAX
)
1716 sprintf(logBuff
, "Section [LOGGING], Invalid Logging Level: %s, ignored", myGetToken(iniStr
, 0));
1717 logMess(logBuff
, 1);
1720 WORD wVersionRequested
= MAKEWORD(1, 1);
1721 WSAStartup(wVersionRequested
, &cfig
.wsaData
);
1723 if (cfig
.wsaData
.wVersion
!= wVersionRequested
)
1725 sprintf(logBuff
, "WSAStartup Error");
1726 logMess(logBuff
, 1);
1729 if (getSection("LISTEN-ON", iniStr
, 1, iniFile
))
1731 char *iniStrPtr
= myGetToken(iniStr
, 0);
1733 for (int i
= 0; i
< MAX_SERVERS
&& iniStrPtr
[0]; iniStrPtr
= myGetToken(iniStrPtr
, 1))
1735 strncpy(name
, iniStrPtr
, UCHAR_MAX
);
1737 char *dp
= strchr(name
, ':');
1745 DWORD ip
= my_inet_addr(name
);
1747 if (isIP(name
) && ip
)
1749 for (BYTE j
= 0; j
< MAX_SERVERS
; j
++)
1751 if (cfig
.servers
[j
] == ip
)
1753 else if (!cfig
.servers
[j
])
1755 cfig
.servers
[j
] = ip
;
1756 cfig
.ports
[j
] = port
;
1764 sprintf(logBuff
, "Warning: Section [LISTEN-ON], Invalid IP Address %s, ignored", iniStrPtr
);
1765 logMess(logBuff
, 1);
1770 if (getSection("HOME", iniStr
, 1, iniFile
))
1772 char *iniStrPtr
= myGetToken(iniStr
, 0);
1773 for (; iniStrPtr
[0]; iniStrPtr
= myGetToken(iniStrPtr
, 1))
1775 mySplit(name
, value
, iniStrPtr
, '=');
1778 if (!cfig
.homes
[0].alias
[0] && cfig
.homes
[0].target
[0])
1780 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", iniStrPtr
);
1781 logMess(logBuff
, 1);
1783 else if (strchr(name
, notFileSep
) || strchr(name
, fileSep
) || strchr(name
, '>') || strchr(name
, '<') || strchr(name
, '.'))
1785 sprintf(logBuff
, "Section [HOME], invalid chars in alias %s, entry ignored", name
);
1786 logMess(logBuff
, 1);
1788 else if (name
[0] && strlen(name
) < 64 && value
[0])
1790 for (int i
= 0; i
< 8; i
++)
1792 if (cfig
.homes
[i
].alias
[0] && !strcasecmp(name
, cfig
.homes
[i
].alias
))
1794 sprintf(logBuff
, "Section [HOME], Duplicate Entry: %s ignored", iniStrPtr
);
1795 logMess(logBuff
, 1);
1798 else if (!cfig
.homes
[i
].alias
[0])
1800 strcpy(cfig
.homes
[i
].alias
, name
);
1801 strcpy(cfig
.homes
[i
].target
, value
);
1803 if (cfig
.homes
[i
].target
[strlen(cfig
.homes
[i
].target
) - 1] != fileSep
)
1805 tempbuff
[0] = fileSep
;
1807 strcat(cfig
.homes
[i
].target
, tempbuff
);
1816 sprintf(logBuff
, "Section [HOME], alias %s too large", name
);
1817 logMess(logBuff
, 1);
1820 else if (!cfig
.homes
[0].alias
[0] && !cfig
.homes
[0].target
[0])
1822 strcpy(cfig
.homes
[0].target
, name
);
1824 if (cfig
.homes
[0].target
[strlen(cfig
.homes
[0].target
) - 1] != fileSep
)
1826 tempbuff
[0] = fileSep
;
1828 strcat(cfig
.homes
[0].target
, tempbuff
);
1831 else if (cfig
.homes
[0].alias
[0])
1833 sprintf(logBuff
, "Section [HOME], alias and bare path mixup, entry %s ignored", iniStrPtr
);
1834 logMess(logBuff
, 1);
1836 else if (cfig
.homes
[0].target
[0])
1838 sprintf(logBuff
, "Section [HOME], Duplicate Path: %s ignored", iniStrPtr
);
1839 logMess(logBuff
, 1);
1843 sprintf(logBuff
, "Section [HOME], missing = sign, Invalid Entry: %s ignored", iniStrPtr
);
1844 logMess(logBuff
, 1);
1849 if (!cfig
.homes
[0].target
[0])
1851 GetModuleFileName(NULL
, cfig
.homes
[0].target
, UCHAR_MAX
);
1852 char *iniFileExt
= strrchr(cfig
.homes
[0].target
, fileSep
);
1853 *(++iniFileExt
) = 0;
1856 cfig
.fileRead
= true;
1858 if (getSection("TFTP-OPTIONS", iniStr
, 1, iniFile
))
1860 char *iniStrPtr
= myGetToken(iniStr
, 0);
1861 for (;strlen(iniStrPtr
);iniStrPtr
= myGetToken(iniStrPtr
, 1))
1863 mySplit(name
, value
, iniStrPtr
, '=');
1866 if (!strcasecmp(name
, "blksize"))
1868 DWORD tblksize
= atol(value
);
1872 else if (tblksize
> USHRT_MAX
- 32)
1873 blksize
= USHRT_MAX
- 32;
1877 else if (!strcasecmp(name
, "threadpoolsize"))
1879 minThreads
= atol(value
);
1882 else if (minThreads
> 100)
1885 else if (!strcasecmp(name
, "timeout"))
1887 timeout
= atol(value
);
1890 else if (timeout
> UCHAR_MAX
)
1891 timeout
= UCHAR_MAX
;
1893 else if (!strcasecmp(name
, "Read"))
1895 if (strchr("Yy", *value
))
1896 cfig
.fileRead
= true;
1898 cfig
.fileRead
= false;
1900 else if (!strcasecmp(name
, "Write"))
1902 if (strchr("Yy", *value
))
1903 cfig
.fileWrite
= true;
1905 cfig
.fileWrite
= false;
1907 else if (!strcasecmp(name
, "Overwrite"))
1909 if (strchr("Yy", *value
))
1910 cfig
.fileOverwrite
= true;
1912 cfig
.fileOverwrite
= false;
1914 else if (!strcasecmp(name
, "port-range"))
1916 char *ptr
= strchr(value
, '-');
1920 cfig
.minport
= atol(value
);
1921 cfig
.maxport
= atol(++ptr
);
1923 if (cfig
.minport
< 1024 || cfig
.minport
>= USHRT_MAX
|| cfig
.maxport
< 1024 || cfig
.maxport
>= USHRT_MAX
|| cfig
.minport
> cfig
.maxport
)
1928 sprintf(logBuff
, "Invalid port range %s", value
);
1929 logMess(logBuff
, 1);
1934 sprintf(logBuff
, "Invalid port range %s", value
);
1935 logMess(logBuff
, 1);
1940 sprintf(logBuff
, "Warning: unknown option %s, ignored", name
);
1941 logMess(logBuff
, 1);
1947 if (getSection("ALLOWED-CLIENTS", iniStr
, 1, iniFile
))
1949 char *iniStrPtr
= myGetToken(iniStr
, 0);
1950 for (int i
= 0; i
< 32 && iniStrPtr
[0]; iniStrPtr
= myGetToken(iniStrPtr
, 1))
1954 mySplit(name
, value
, iniStrPtr
, '-');
1955 rs
= htonl(my_inet_addr(name
));
1958 re
= htonl(my_inet_addr(value
));
1962 if (rs
&& rs
!= INADDR_NONE
&& re
&& re
!= INADDR_NONE
&& rs
<= re
)
1964 cfig
.hostRanges
[i
].rangeStart
= rs
;
1965 cfig
.hostRanges
[i
].rangeEnd
= re
;
1970 sprintf(logBuff
, "Section [ALLOWED-CLIENTS] Invalid entry %s in ini file, ignored", iniStrPtr
);
1971 logMess(logBuff
, 1);
1976 // if (!cfig.servers[0])
1981 for (int j
= 0; j
< MAX_SERVERS
; j
++)
1983 if (j
&& !cfig
.servers
[j
])
1986 cfig
.tftpConn
[i
].sock
= socket(PF_INET
,
1990 if (cfig
.tftpConn
[i
].sock
== INVALID_SOCKET
)
1992 sprintf(logBuff
, "Failed to Create Socket");
1993 logMess(logBuff
, 1);
1997 cfig
.tftpConn
[i
].addr
.sin_family
= AF_INET
;
2002 cfig
.tftpConn
[i
].addr
.sin_addr
.s_addr
= cfig
.servers
[j
];
2003 cfig
.tftpConn
[i
].addr
.sin_port
= htons(cfig
.ports
[j
]);
2005 socklen_t nRet
= bind(cfig
.tftpConn
[i
].sock
,
2006 (sockaddr
*)&cfig
.tftpConn
[i
].addr
,
2007 sizeof(struct sockaddr_in
)
2010 if (nRet
== SOCKET_ERROR
)
2012 closesocket(cfig
.tftpConn
[i
].sock
);
2013 sprintf(logBuff
, "%s Port %u, bind failed", IP2String(tempbuff
, cfig
.servers
[j
]), cfig
.ports
[j
]);
2014 logMess(logBuff
, 1);
2018 if (cfig
.maxFD
< cfig
.tftpConn
[i
].sock
)
2019 cfig
.maxFD
= cfig
.tftpConn
[i
].sock
;
2021 cfig
.tftpConn
[i
].server
= cfig
.tftpConn
[i
].addr
.sin_addr
.s_addr
;
2022 cfig
.tftpConn
[i
].port
= htons(cfig
.tftpConn
[i
].addr
.sin_port
);
2028 if (!cfig
.tftpConn
[0].port
)
2030 sprintf(logBuff
, "no listening interfaces available, stopping..\nPress Enter to exit\n");
2031 logMess(logBuff
, 1);
2037 printf("starting TFTP...\n");
2041 sprintf(logBuff
, "starting TFTP service");
2042 logMess(logBuff
, 1);
2045 for (int i
= 0; i
< MAX_SERVERS
; i
++)
2046 if (cfig
.homes
[i
].target
[0])
2048 sprintf(logBuff
, "alias /%s is mapped to %s", cfig
.homes
[i
].alias
, cfig
.homes
[i
].target
);
2049 logMess(logBuff
, 1);
2052 if (cfig
.hostRanges
[0].rangeStart
)
2056 for (WORD i
= 0; i
<= sizeof(cfig
.hostRanges
) && cfig
.hostRanges
[i
].rangeStart
; i
++)
2058 sprintf(logBuff
, "%s", "permitted clients: ");
2059 sprintf(temp
, "%s-", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeStart
)));
2060 strcat(logBuff
, temp
);
2061 sprintf(temp
, "%s", IP2String(tempbuff
, htonl(cfig
.hostRanges
[i
].rangeEnd
)));
2062 strcat(logBuff
, temp
);
2063 logMess(logBuff
, 1);
2068 sprintf(logBuff
, "%s", "permitted clients: all");
2069 logMess(logBuff
, 1);
2074 sprintf(logBuff
, "server port range: %u-%u", cfig
.minport
, cfig
.maxport
);
2075 logMess(logBuff
, 1);
2079 sprintf(logBuff
, "server port range: all");
2080 logMess(logBuff
, 1);
2083 sprintf(logBuff
, "max blksize: %u", blksize
);
2084 logMess(logBuff
, 1);
2085 sprintf(logBuff
, "default blksize: %u", 512);
2086 logMess(logBuff
, 1);
2087 sprintf(logBuff
, "default timeout: %u", timeout
);
2088 logMess(logBuff
, 1);
2089 sprintf(logBuff
, "file read allowed: %s", cfig
.fileRead
? "Yes" : "No");
2090 logMess(logBuff
, 1);
2091 sprintf(logBuff
, "file create allowed: %s", cfig
.fileWrite
? "Yes" : "No");
2092 logMess(logBuff
, 1);
2093 sprintf(logBuff
, "file overwrite allowed: %s", cfig
.fileOverwrite
? "Yes" : "No");
2094 logMess(logBuff
, 1);
2098 sprintf(logBuff
, "logging: %s", cfig
.logLevel
> 1 ? "all" : "errors");
2099 logMess(logBuff
, 1);
2102 lEvent
= CreateEvent(
2103 NULL
, // default security descriptor
2104 FALSE
, // ManualReset
2106 TEXT("AchalTFTServerLogEvent")); // object name
2110 printf("CreateEvent error: %lu\n", GetLastError());
2113 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2115 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2116 logMess(logBuff
, 0);
2120 tEvent
= CreateEvent(
2121 NULL
, // default security descriptor
2122 FALSE
, // ManualReset
2124 TEXT("AchalTFTServerThreadEvent")); // object name
2128 printf("CreateEvent error: %lu\n", GetLastError());
2131 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2133 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2134 logMess(logBuff
, 0);
2138 sEvent
= CreateEvent(
2139 NULL
, // default security descriptor
2140 FALSE
, // ManualReset
2142 TEXT("AchalTFTServerSocketEvent")); // object name
2146 printf("CreateEvent error: %lu\n", GetLastError());
2149 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2151 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2152 logMess(logBuff
, 0);
2156 cEvent
= CreateEvent(
2157 NULL
, // default security descriptor
2158 FALSE
, // ManualReset
2160 TEXT("AchalTFTServerCountEvent")); // object name
2164 printf("CreateEvent error: %lu\n", GetLastError());
2167 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
2169 sprintf(logBuff
, "CreateEvent opened an existing Event\nServer May already be Running");
2170 logMess(logBuff
, 0);
2176 for (int i
= 0; i
< minThreads
; i
++)
2179 processRequest
, // thread function
2180 0, // default security attributes
2181 NULL
); // argument to thread function
2184 sprintf(logBuff
, "thread pool size: %u", minThreads
);
2185 logMess(logBuff
, 1);
2188 for (int i
= 0; i
< MAX_SERVERS
&& cfig
.tftpConn
[i
].port
; i
++)
2190 sprintf(logBuff
, "listening on: %s:%i", IP2String(tempbuff
, cfig
.tftpConn
[i
].server
), cfig
.tftpConn
[i
].port
);
2191 logMess(logBuff
, 1);
2195 void logMess(char *logBuff
, BYTE logLevel
)
2197 WaitForSingleObject(lEvent
, INFINITE
);
2200 printf("%s\n", logBuff
);
2201 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2203 char currentTime
[32];
2204 time_t t
= time(NULL
);
2205 tm
*ttm
= localtime(&t
);
2206 strftime(currentTime
, sizeof(currentTime
), "%d-%b-%y %X", ttm
);
2207 fprintf(cfig
.logfile
, "[%s] %s\n", currentTime
, logBuff
);
2208 fflush(cfig
.logfile
);
2213 void logMess(request
*req
, BYTE logLevel
)
2215 WaitForSingleObject(lEvent
, INFINITE
);
2221 if (!req
->serverError
.errormessage
[0])
2222 sprintf(req
->serverError
.errormessage
, strerror(errno
));
2225 printf("Client %s:%u %s, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->path
, req
->serverError
.errormessage
);
2227 printf("Client %s:%u, %s\n", IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2229 else if (cfig
.logfile
&& logLevel
<= cfig
.logLevel
)
2231 char currentTime
[32];
2232 time_t t
= time(NULL
);
2233 tm
*ttm
= localtime(&t
);
2234 strftime(currentTime
, sizeof(currentTime
), "%d-%b-%y %X", ttm
);
2237 fprintf(cfig
.logfile
, "[%s] Client %s:%u %s, %s\n", currentTime
, IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->path
, req
->serverError
.errormessage
);
2239 fprintf(cfig
.logfile
, "[%s] Client %s:%u, %s\n", currentTime
, IP2String(tempbuff
, req
->client
.sin_addr
.s_addr
), ntohs(req
->client
.sin_port
), req
->serverError
.errormessage
);
2241 fflush(cfig
.logfile
);