错误代码1024 TFTP服务器

error code 1024 tftp server

本文关键字:服务器 TFTP 1024 错误代码      更新时间:2023-10-16

我在C中编写了TFTP服务器,并用终端上的TFTP命令对其进行测试。但是,在大多数情况下,当我尝试发送RRQ时,我会收到以下内容:

tftp> get a.txt
sent RRQ <file=a.txt, mode=netascii>
received ERROR <code=4, msg=>
Error code 1024: 

其他案例案件包括:

tftp> get a.txt
sent RRQ <file=a.txt, mode=netascii>
received DATA <block=20334, 512 bytes>
discarded 4 packets

和这个:这看起来可能正确,但几乎没有发生。我用来测试的文本文件是857个字节。

sent ACK <block=1>
received DATA <block=1, 512 bytes>
sent ACK <block=1>
received DATA <block=2, 345 bytes>
Received 857 bytes in 0.0 seconds

这是我的代码的一部分这里的缓冲区是一个尺寸512的字符阵列,为了简化代码,我删除了一些错误处理代码感谢谁可以帮助

            #include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/select.h> 
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <cerrno>

//define opcode for later use
enum opcode {
     RRQ = 1,
     WRQ,
     DATA,
     ACK,
     ERROR
};

void handle_write(struct sockaddr_in * sock_info, char* filename, int BUF_LEN){
    //printf("Received write request + %dn", WRQ);
    return;
}
void handle_error(unsigned short int * opcode_ptr, char* buffer, socklen_t sockaddr_len, int server_socket, struct sockaddr_in * sock_info, const char* errormsg){
     ssize_t n;
     *opcode_ptr = htons(ERROR);
     *(opcode_ptr + 1) = htons(1);
     *(buffer + 4) = 0;
     //memcpy(buffer+4, errormsg, strlen(errormsg));
 intr_send:
     n = sendto(server_socket, buffer, 5, 0,
                (struct sockaddr *)sock_info, sockaddr_len);
     if(n < 0) {
         if(errno == EINTR) goto intr_send;
         perror(errormsg);
         exit(-1);
     }
    return;
}
int main() {
    int BUF_LEN = 516;
    ssize_t n;
    char buffer[BUF_LEN];
    socklen_t sockaddr_len;
    int server_socket;
    struct sigaction act;
    unsigned short int opcode;
    unsigned short int * opcode_ptr;
    struct sockaddr_in sock_info;
    memset(&sock_info, 0, sockaddr_len);
    //----------setup the server----------------//
    sock_info.sin_addr.s_addr = htonl(INADDR_ANY);
    sock_info.sin_port = htons(5743);
    sock_info.sin_family = PF_INET;
    if((server_socket = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        exit(-1);
    }
    sockaddr_len = sizeof(sock_info);
    if(bind(server_socket, (struct sockaddr *)&sock_info, sockaddr_len) < 0) {
        perror("bind");
        exit(-1);
    }
    getsockname(server_socket, (struct sockaddr *)&sock_info, &sockaddr_len);
    printf("UDP server listening on port: %dn", ntohs(sock_info.sin_port));
    //----------setup the server----------------//
    while(1){
    intr_recv:
         n = recvfrom(server_socket, buffer, BUF_LEN, 0, (struct sockaddr *)&sock_info, &sockaddr_len);
         if(n < 0) {
            if(errno == EINTR) goto intr_recv;
            perror("recvfrom()");
            exit(-1);
        }
        opcode_ptr = (unsigned short int *)buffer;
        opcode = ntohs(*opcode_ptr);    //the opcode will be either RRQ or WRQ according to the test
        if(opcode != RRQ && opcode != WRQ) {
            /* Illegal TFTP Operation */
            handle_error(opcode_ptr, buffer, sockaddr_len, server_socket, &sock_info, "invalid command");
        }
        else {
            if(fork() == 0) {
                /* Child - handle the request */
                FILE* fd;
                char* filename;
                filename = strdup(buffer+2);  //this is the filename to be read (i.e. a.txt)
                printf("request receivedn");
                char data[512];
                //----------------------------------handle read request-------------------------------------//
                if(opcode == RRQ){
                    int blocknumber = 0;
                    int i = 0; //counter for loop
                    fd = fopen(filename, "r");
                    free(filename);
                    //uint8_t data[512];
                    ssize_t datalen, n;
                    int done = 0;   //this is a boolean indicator that indicates whether the packet transfering process is done or not.
                    while(!done){
                        datalen = fread(data, 1, 512, fd);
                        blocknumber++;
                        if(datalen < 512){
                            done = 1;       //according to rfc 1350, the last packet will have a data length less than 512 bytes.
                        }
                        //for(i = 5; i > 0; i--){
                        *opcode_ptr = htons(DATA);
                        opcode = ntohs(*opcode_ptr);
                        *(opcode_ptr + 1) = htons(blocknumber);
                        memcpy(buffer + 4, data, datalen);
                        buffer[datalen + 4] = '';
                        //*(buffer + 4) = 0;
                        //printf("%d  %sn", datalen, buffer+2);
                        n = sendto(server_socket, buffer, 4 + datalen, 0, (struct sockaddr *)&sock_info, sockaddr_len);
                        if(n < 0){
                            perror("sendto() failed");
                            exit(-1);
                        }
                        //printf("done %dn", done);
                        //char buffer[512];
                        n = recvfrom(server_socket, buffer, sizeof(buffer), 0, (struct sockaddr *)&sock_info, &sockaddr_len);
                        opcode_ptr = (unsigned short int *)buffer;
                        opcode = ntohs(*opcode_ptr);
                        if(n >= 0 && n < 4){
                            //handle_error(opcode_ptr, buffer, sockaddr_len, server_socket, &sock_info, "invalid request size");
                        }
                         if(n > 4){
                             break;
                         }
                         //}
                        //if(i != 0){
                        //    printf("Transfer timeout!n");
                        //    exit(1);
                        //}
                        //printf("opcode is %dn", opcode);
                        if(opcode == ERROR){
                            printf("Error receivedn");
                            exit(1);
                        }
                        if(opcode != ACK){
                            printf("Invalid message receivedn");
                            exit(1);
                        }
                    }
                }
                //----------------------------------handle read request-------------------------------------//

                //----------------------------------handle write request------------------------------------//
                //----------------------------------handle write request------------------------------------//
                close(server_socket);
                break;
            }
            else {
                /* Parent - continue to wait */
            }
        }
    }



    return EXIT_SUCCESS;
}

我读取了您的代码,但未通过执行。

进行测试。

与RFC 1350进行比较,我发现的是

  • 数据字段最高为512个字节,因此512字节buffer还不够,因为没有用于标头的空间(OPCODE和BLOCK#(。您至少需要4个字节。
  • 您通过memcpy()buffer + 2写数据。这应该破坏块号。似乎应该使用buffer + 4
  • 不需要buffer[datalen + 2] = '';。我认为您应该将其删除,因为它会销毁数据或导致缓冲区过度。
  • 您应该关闭处理读取请求后打开的文件。