📄 tftpserver.cpp
字号:
request *req1 = tftpCache[req.mapname]; if (!req1) tftpCache.erase(req.mapname); //printf("%u\n",req1); //printf("Here\n"); if (req1) { req1->bytesRecd = req.bytesRecd; if (ntohs(datain->opcode) == 3 && req1->opcode == 2) { if ((WORD)req1->bytesRecd <= req1->blksize + 4) { req1->tblock = req1->block + 1; if (req1->attempt <= 3 && ntohs(datain->block) == req1->tblock) { req1->block = req1->tblock; req1->fblock++; req1->attempt = 0; req1->acout.opcode = htons(4); req1->acout.block = ntohs(req1->block); processRecv(req1); } } else { req1->serverError.opcode = htons(5); req1->serverError.errorcode = htons(4); req1->bytesSent = sendto(cfig.tftpConn[req1->sockInd].sock, (const char*)&req1->serverError, strlen(req1->serverError.errormessage) + 5, 0, (sockaddr*)&req1->client, req1->clientsize); sprintf(req1->serverError.errormessage, "Error: Incoming Packet too large"); logMess(req1, 1); req1->attempt = UCHAR_MAX; } } else if (ntohs(datain->opcode) == 4 && req1->opcode == 1) { if (req1->bytesRecd >= 4) { if (req1->attempt <= 3 && ntohs(datain->block) == req1->block) { req1->block++; req1->fblock++; req1->attempt = 0; processSend(req1); } } } else if (req1->bytesRecd > 512) { req1->serverError.opcode = htons(5); req1->serverError.errorcode = htons(4); req1->bytesSent = sendto(cfig.tftpConn[req1->sockInd].sock, (const char*)&req1->serverError, strlen(req1->serverError.errormessage) + 5, 0, (sockaddr*)&req1->client, req1->clientsize); sprintf(req1->serverError.errormessage, "Error: Incoming Packet too large"); logMess(req1, 1); req1->attempt = UCHAR_MAX; } else if (ntohs(datain->opcode) == 1 || ntohs(datain->opcode) == 2) { if (req1->file) { fclose(req1->file); req1->file = 0; } if (!processNew(&req)) { memcpy(req1, &req, sizeof(request)); } } else if (ntohs(datain->opcode) == 5) { sprintf(req1->serverError.errormessage, "Error %i at Client, %s", ntohs(datain->block), &datain->buffer); logMess(req1, 1); req1->attempt = UCHAR_MAX; if (req1->file) { fclose(req1->file); req1->file = 0; } } else { req1->serverError.opcode = htons(5); req1->serverError.errorcode = htons(4); sprintf(req1->serverError.errormessage, "Unexpected Option Code %u", ntohs(datain->opcode)); req1->bytesSent = sendto(cfig.tftpConn[req1->sockInd].sock, (const char*)&req1->serverError, strlen(req1->serverError.errormessage) + 5, 0, (sockaddr*)&req1->client, req1->clientsize); logMess(req1, 1); req1->attempt = UCHAR_MAX; if (req1->file) { fclose(req1->file); req1->file = 0; } } } else if (req.bytesRecd < 4 || errno) { req.serverError.opcode = htons(5); req.serverError.errorcode = htons(0); sprintf(req.serverError.errormessage, "Communication Error"); logMess(&req, 1); continue; } else if (ntohs(datain->opcode) != 1 && ntohs(datain->opcode) != 2) { req.serverError.opcode = htons(5); req.serverError.errorcode = htons(5); sprintf(req.serverError.errormessage, "Unknown transfer ID"); req.bytesSent = sendto(cfig.tftpConn[i].sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize); logMess(&req, 1); } else if (req.bytesRecd > 512) { req.serverError.opcode = htons(5); req.serverError.errorcode = htons(4); sprintf(req.serverError.errormessage, "Error: Incoming Packet too large"); req.bytesSent = sendto(cfig.tftpConn[i].sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize); logMess(&req, 1); } else if (ntohs(datain->opcode) == 5) { sprintf(req.serverError.errormessage, "Error %i at Client, %s", ntohs(datain->block), &datain->buffer); logMess(&req, 1); continue; } else { if (cfig.hostRanges[0].rangeStart) { DWORD iip = ntohl(req.client.sin_addr.s_addr); BYTE allowed = false; for (WORD j = 0; j <= sizeof(cfig.hostRanges) && cfig.hostRanges[j].rangeStart; j++) { if (iip >= cfig.hostRanges[j].rangeStart && iip <= cfig.hostRanges[j].rangeEnd) { allowed = true; break; } } if (!allowed) { req.serverError.opcode = htons(5); req.serverError.errorcode = htons(2); strcpy(req.serverError.errormessage, "Access Denied"); logMess(&req, 1); req.bytesSent = sendto(cfig.tftpConn[i].sock, (const char*)&req.serverError, strlen(req.serverError.errormessage) + 5, 0, (sockaddr*)&req.client, req.clientsize); continue; } } if (!processNew(&req)) { request *req1 = (request*)calloc(1, sizeof(request)); if (!req1) { sprintf(logBuff,"Memory Error"); logMess(logBuff, 1); continue; } memcpy(req1, &req, sizeof(request)); tftpCache[req1->mapname] = req1; tftpAge.insert(pair<long, request*>(req1->expiry, req1)); } } } } myMultiMap::iterator p = tftpAge.begin(); myMultiMap::iterator q; time_t currentTime = time(NULL); while (p != tftpAge.end()) { if (!tftpAge.size()) break; request *req = p->second; if (p->first > currentTime) { break; } else if (p->first < req->expiry && req->expiry > currentTime) { q = p; p++; tftpAge.erase(q); tftpAge.insert(pair<long, request*>(req->expiry, req)); } else if (req->expiry <= currentTime && req->attempt >= 3) { if (req->attempt < UCHAR_MAX) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); if (req->fblock && !req->block) strcpy(req->serverError.errormessage, "Large File, Block# Rollover not supported by Client"); else strcpy(req->serverError.errormessage, "Timeout"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*) &req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); } q = p; p++; tftpAge.erase(q); tftpCache.erase(req->mapname); clean(req); } else if (req->expiry <= currentTime) { if (ntohs(req->acout.opcode) == 3) { if (processSend(req)) req->attempt = 255; else { req->attempt++; req->expiry = currentTime + req->timeout; } } else { errno = 0; req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->acout, req->bytesSent, 0, (sockaddr*)&req->client, req->clientsize); if (errno) req->attempt = 255; else { req->attempt++; req->expiry = currentTime + req->timeout; } } p++; } else p++; } } while (kRunning); } }}void closeConn(){ kRunning = false; sprintf(logBuff, "Closing Network Connections..."); logMess(logBuff, 1); for (int i = 0; i < MAX_SERVERS && cfig.tftpConn[i].server; i++) close(cfig.tftpConn[i].sock); sprintf(logBuff, "TFTP Server Stopped !"); logMess(logBuff, 1); //exit(EXIT_SUCCESS);}void catch_int(int sig_num){ closeConn();}int processNew(request *req){ req->block = 0; req->bytesSent = 0; req->blksize = 512; req->timeout = timeout; req->expiry = time(NULL) + req->timeout; req->opcode = ntohs(datain->opcode); char *inPtr = (char*)datain; *(inPtr + (req->bytesRecd - 1)) = 0; inPtr += 2; req->filename = inPtr; if (!strlen(req->filename) || strlen(req->filename) > 255) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(4); strcpy(req->serverError.errormessage, "Malformed Request, Invalid/Missing Filename"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); req->attempt = UCHAR_MAX; logMess(req, 1); return 1; } inPtr += strlen(inPtr) + 1; req->mode = inPtr; if (!strlen(req->mode) || strlen(req->mode) > 25) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(4); strcpy(req->serverError.errormessage, "Malformed Request, Invalid/Missing Mode"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); req->attempt = UCHAR_MAX; logMess(req, 1); return 1; } inPtr += strlen(inPtr) + 1; for (WORD i = 0; i < strlen(req->filename); i++) if (req->filename[i] == '\\') req->filename[i] = '/'; if (strstr(req->filename, "../")) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); strcpy(req->serverError.errormessage, "Access violation"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; }/* if (strchr(req->filename, '~') || strchr(req->filename, '`') || strchr(req->filename, '$') || strchr(req->filename, '<') || strchr(req->filename, '>') || strchr(req->filename, ';') || strchr(req->filename, ';')) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(0); strcpy(req->serverError.errormessage, "Invalid Filename"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; }*/ if (req->filename[0] == '/') req->filename++; if (!cfig.homes[0].alias[0]) { if (strlen(cfig.homes[0].target) + strlen(req->filename) >= sizeof(req->path)) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(4); strcpy(req->serverError.errormessage, "Filename too large"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } strcpy(req->path, cfig.homes[0].target); strcat(req->path, req->filename); } else { char *bname = strchr(req->filename, '/'); if (bname) { *bname = 0; bname++; } else { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(1); sprintf(req->serverError.errormessage, "Missing directory/alias"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } for (int i = 0; i < 8; i++) { if (cfig.homes[i].alias[0] && !strcasecmp(req->filename, cfig.homes[i].alias)) { if (strlen(cfig.homes[i].target) + strlen(bname) >= sizeof(req->path)) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(4); strcpy(req->serverError.errormessage, "Filename too large"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*) &req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } strcpy(req->path, cfig.homes[i].target); strcat(req->path, bname); break; } else if (i == 7 || !cfig.homes[i].alias[0]) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(1); sprintf(req->serverError.errormessage, "No such directory/alias"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*) &req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } } } if (ntohs(datain->opcode) == 1) { errno = 0; if (cfig.fileRead) { if (!strcasecmp(req->mode, "netascii") || !strcasecmp(req->mode, "ascii")) req->file = fopen(req->path, "rt"); else req->file = fopen(req->path, "rb"); } if (errno || !cfig.fileRead || !req->file) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(1); strcpy(req->serverError.errormessage, "File Not Found/No Access"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } } else { req->file = fopen(req->path, "rb"); if (req->file) { fclose(req->file); req->file = NULL; if (!cfig.fileOverwrite) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(6); strcpy(req->serverError.errormessage, "File already exists"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } } else if (!cfig.fileWrite) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(2); strcpy(req->serverError.errormessage, "Create File Access Denied"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } errno = 0; if (strcasecmp(req->mode, "netascii")) req->file = fopen(req->path, "wb"); else req->file = fopen(req->path, "wt"); if (errno || !req->file) { req->serverError.opcode = htons(5); req->serverError.errorcode = htons(1); strcpy(req->serverError.errormessage, "Invalid Path or No Access"); req->bytesSent = sendto(cfig.tftpConn[req->sockInd].sock, (const char*)&req->serverError, strlen(req->serverError.errormessage) + 5, 0, (sockaddr*)&req->client, req->clientsize); logMess(req, 1); req->attempt = UCHAR_MAX; return 1; } } if (*inPtr) { char *outPtr = req->acout.buffer; req->acout.opcode = htons(6); DWORD val; while (*inPtr) { //printf("%s", inPtr); if (!strcasecmp(inPtr, "blksize")) { strcpy(outPtr, inPtr); outPtr += strlen(outPtr) + 1; inPtr += strlen(inPtr) + 1; val = atol(inPtr); if (val < 512) val = 512; else if (val > blksize) val = blksize; req->blksize = val;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -