📄 tftpserver.c
字号:
/*************************************************************************** Copyright (C) 2005 by Achal Dhir ** achaldhir@gmail.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the ** Free Software Foundation, Inc., ** 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ****************************************************************************/// modified by chen yong, 2007.06.10 #include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <unistd.h>#include <signal.h>#include <stdio.h>#include <fcntl.h>#include <errno.h>#include <sys/time.h>#include <sys/ioctl.h>#include <time.h>#include <stdlib.h>#include <limits.h>#include <memory.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include "tftpserver.h"//Function prototypesint init();int getSection(char *sectionName, char *buffer, int sizeofbuffer, char *fileName);char *myLower(char *string);char *myUpper(char *string);char *cleanstr(char* buff, int next);BYTE isIP(char *string);DWORD my_inet_addr(char*);char * IP2String(DWORD ip);void logMess(BYTE);void logMess_2(struct request *req, BYTE messLevel);//Global Variablesint verbatim;char iniFile[]="tftpserver.ini";char tempbuff[256];char logBuff[512];struct data2 cfig;WORD interval = 3;void *ProcessRequest(void *lpParam);void cleanReq(struct request*);int main(int argc, char **argv){ verbatim = 0; struct timeval tv; fd_set readfds; int fdsReady; int i; struct request * req; verbatim = (argc > 1); if (verbatim) { if (init() == 0) { exit(1); } printf("\nAccepting requests..\n"); while (1) { FD_ZERO(&readfds); tv.tv_sec = 20; tv.tv_usec = 0; errno = 0; fdsReady = select(cfig.sock + 1, &readfds, NULL, NULL, &tv); FD_SET(cfig.sock, &readfds); if (FD_ISSET(cfig.sock, &readfds)) { req = (struct request *)malloc(sizeof(struct request)); if (!req) { sprintf(logBuff,"Memory Error"); logMess(1); continue; } req->clientsize = sizeof(req->client); errno = 0; req->bytesReceived = recvfrom(cfig.sock, (char*)&(req->datain), sizeof(req->datain), 0, (struct sockaddr *)&(req->client), &req->clientsize); req->knock = cfig.sock; if (!errno) { if (req->bytesReceived > 0 && (ntohs(req->datain.opcode) == 1 || ntohs(req->datain.opcode) == 2)) { pthread_create(&req->threadId, 0, ProcessRequest, (void*)req); if (!req->threadId) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Thread Creation Error"); logMess_2(req, 2); req->bytesSent = sendto(req->knock, (const char*)&(req->serverError), strlen(req->serverError.errormessage) + 5, 0, (struct sockaddr*)&(req->client), req->clientsize); free(req); } } else if (req->bytesReceived > 0 && (htons(req->datain.opcode) == 5)) { sprintf(req->serverError.errormessage, "Error Code %i at Client, %s", ntohs(req->clientError.errorcode), req->clientError.errormessage); logMess_2(req, 2); free(req); } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(4); sprintf(req->serverError.errormessage, "Invalid Option Code %i", ntohs(req->datain.opcode)); logMess_2(req, 2); req->bytesSent = sendto(req->knock, (const char*)&(req->serverError), strlen(req->serverError.errormessage) + 5, 0, (struct sockaddr*)&(req->client), req->clientsize); free(req); } } else { sprintf(req->serverError.errormessage, "Communication Error"); logMess_2(req, 1); free(req); } } } }}int init(){ socklen_t nRet; memset(&cfig, 0, sizeof(cfig)); sprintf(cfig.homedir, "/home/yongchen/test/"); cfig.overwrite = 0; cfig.logLevel = 2; cfig.minport = 30000; cfig.maxport = 30020; cfig.server = inet_addr("192.168.130.154"); cfig.port = 69; cfig.sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (cfig.sock == -1) { sprintf(logBuff, "Failed to Create Socket"); logMess(1); return 0; } cfig.addr.sin_family = AF_INET; cfig.addr.sin_addr.s_addr = cfig.server; cfig.addr.sin_port = htons(cfig.port); nRet = bind(cfig.sock, (struct sockaddr *)&cfig.addr, sizeof(struct sockaddr_in)); if (nRet == -1) { close(cfig.sock); sprintf(logBuff, "%s Port %u, bind failed, %s", IP2String(cfig.server), cfig.port, strerror(errno)); logMess(1); return 0; } if (verbatim) { printf("\nStarting TFTP...\n"); } return 1;}char * IP2String(DWORD ip){ struct in_addr inaddr; inaddr.s_addr = ip; sprintf(tempbuff, "%s", inet_ntoa(inaddr)); return tempbuff;}BYTE isIP(char *string){ int j = 0; for ( ; *string; string++) { if (*string == '.') j++; else if (*string < '0' || *string > '9') return 0; } if (j == 3) return 1; else return 0;}void logMess(BYTE messLevel){ if (verbatim) printf("%s\n", logBuff);}DWORD my_inet_addr(char* str){ if (str == NULL) return INADDR_ANY; DWORD x = inet_addr(str); if (x == INADDR_NONE) return INADDR_ANY; else return x;}void logMess_2(struct request *req, BYTE messLevel){ if (verbatim) { if (!req->serverError.errormessage[0]) printf(req->serverError.errormessage, strerror(errno)); if (req->path[0]) printf("Client %s:%u %s, %s\n", inet_ntoa(req->client.sin_addr), ntohs(req->client.sin_port), req->path, req->serverError.errormessage); else printf("Client %s:%u, %s\n", inet_ntoa(req->client.sin_addr), ntohs(req->client.sin_port), req->serverError.errormessage); }}void *ProcessRequest(void *lpParam){ struct request * req = (struct request *)lpParam; req->blksize = 512; req->interval = interval - (interval / 2); WORD comport; struct sockaddr_in service; char * temp; int i; //step1. create socket, bind address, and connect to client. req->m_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (req->m_socket == -1) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Thread Socket Creation Error"); req->bytesSent = sendto(req->knock, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0, (struct sockaddr*) & (req->client), req->clientsize); logMess_2(req, 1); free(req); pthread_exit(NULL); } for (comport = cfig.minport; ;comport++) { service.sin_family = AF_INET; service.sin_addr.s_addr = cfig.server; service.sin_port = htons(comport); if (comport > cfig.maxport) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "No port is free"); req->bytesSent = sendto(req->knock, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0, (struct sockaddr*) & (req->client), req->clientsize); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } else if (bind(req->m_socket, (struct sockaddr *) &service, sizeof(service)) == -1) continue; else break; } if (connect(req->m_socket, (struct sockaddr*)&(req->client), req->clientsize) == -1) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Connect Failed"); req->bytesSent = sendto(req->knock, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0, (struct sockaddr*) & (req->client), req->clientsize); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } temp = (char*) & (req->datain); temp += 2; req->filename = temp; temp += strlen(temp) + 1; req->mode = temp; temp += strlen(temp) + 1; req->alias = req->filename; //step2. handle filename, mode. for (i = 0; i < strlen(req->alias); i++) if (req->alias[i] == '\\') req->alias[i] = '/'; if (strstr(req->alias, "../")) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); strcpy(req->serverError.errormessage, "Access violation"); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); logMess_2(req, 1); cleanReq(req); pthread_exit(NULL); } if (req->alias[0] == '/') req->alias++; strcpy(req->path, cfig.homedir); strcat(req->path, req->alias); req->fblock = 0; if (ntohs(req->datain.opcode) == 1) { errno = 0; if (!strcasecmp(req->mode, "netascii") || !strcasecmp(req->mode, "ascii")) req->file = fopen(req->path, "rt"); else req->file = fopen(req->path, "rb"); if (errno || !req->file) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(1); strcpy(req->serverError.errormessage, "File Not Found"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } } else { if (!cfig.overwrite) { req->file = fopen(req->path, "rb"); if (req->file) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(6); strcpy(req->serverError.errormessage, "File already exists"); logMess_2(req, 1); req->bytesSent = send(req->m_socket, (const char*) & (req->serverError), strlen(req->serverError.errormessage) + 5, 0); cleanReq(req); pthread_exit(NULL); } } errno = 0; if (!strcasecmp(req->mode, "netascii") || !strcasecmp(req->mode, "ascii")) req->file = fopen(req->path, "wt"); else req->file = fopen(req->path, "wb");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -