自己动手学TCP/IP–tftp协议

35 篇文章 0 订阅
12 篇文章 0 订阅

TFTP(Trivial File Transfer Protocol,简单文件传输协议

1.tftp的服务端口号是69

2.tftp是基于udp协议的

3.tftp是明文传输的,是一种比较轻量型的协议,一般用于bootloader加载内核

TFTP工作流程

服务端开启tftp服务,tftp是一种stand_alone服务,不是常驻内存的,是在有需要的时候才去调用的。首先,客户端发送一个读(RRQ:2个字节)或者写(WRQ:2个字节)的请求,数据包的目标端口是69。对于读或者写的报文格式如下:

RRQ/WRQ(2个字节)+文件名(N字节)+0(1字节)+模式(N字节)+0(1字节)

目前模式字段主要有2种:netascii,这是8位的ASCII码形式;另一种是octet,这是8位源数据类型。对于netascii是把回车和换行(CR/LF)解释成两个字节的。可以查看http://www.firefoxbug.net/?p=1041

tftp-server接收到数据包:如果是发现是读(RRQ),就重新随机分配一个端口,直接发送数据(DATA:2个字节)+块编号(2个字节),然后是0~512字节数据包。客户端接收到数据包,发给服务端(ACK:2个字节)+块编号(2个字节)。如果是普通的数据包,那么数据段的大小一定是512字节,如果是最后一个数据包,肯定是小于512字节的。tftp就是通过发现了一个数据段小于512字节的数据包来声明结束文件的传输了。那么一个要传输的文件刚还是512字节的整数倍怎么办呢?tftp会在最后传输一个数据段大小是0包。

tftp-server接收到数据包:如果发现是写(WRQ),服务端就发回(ACK:2个字节)+(块编号0:2个字节)的包,接着客户端就发送(DATA:2个字节)+(块编号1:2个字节)+数据段给服务端,服务端发回(ACK:2个字节)+(块编号1:2个字节)。。。依次发送。

错误信息是系统自定义的,格式主要是error(2个字节)+错误码(2个字节)+错误信息(N个字节)

下面是tftp数据包的格式图


下面是C语言解析tftp包的一小段代码:

struct  tftphdr {
        short   th_opcode;                      /* packet type */
        union {
                unsigned short  tu_block;       /* block # */
                short   tu_code;                /* error code */
                char    tu_stuff[1];            /* request packet stuff */
        } __attribute__ ((__packed__)) th_u;
        char    th_data[1];                     /* data or error string */
} __attribute__ ((__packed__));

// 解析udp包,packet_buffer是用rawsocket抓出来的以太网包,
void ParseUDPPacket(unsigned char *packet_buffer)
{
    struct ethhdr *eth_header;//以太网头
    struct iphdr *ip_header; //ip头
    struct udphdr *udp_header; //tcp头
    eth_header = (struct ethhdr*)packet_buffer;
    ip_header = (struct iphdr*)(packet_buffer + sizeof(struct ethhdr));
    udp_header = (struct udphdr*)(packet_buffer + sizeof(struct ethhdr) + ip_header->ihl*4);
    unsigned char *data = NULL;
    data = (packet_buffer + sizeof(struct ethhdr) + ip_header->ihl*4 + 8);//8代表UDP包头
    struct tftphdr *tp = (struct tftphdr *)data;    //  /usr/include/arpa/tftp.h
    tftp_print(data,ntohs(udp_header->len)-8);  //ntohs(udp_header->len)-8表示udp数据包长度
}

/*
* Print trivial file transfer program requests
*/
void tftp_print(register const u_char *bp, u_int length)
{
    register const struct tftphdr *tp;
    register const u_char *p;
    register int opcode,i;
    static char tstr[] = " [|tftp]";
    char buffer[520] = {'\0'};
    tp = (const struct tftphdr *)bp;

    // printf(" %d", length);
    // printf("length of tftp_data = %d\n",length);

    /* Print tftp request type */

    opcode = EXTRACT_16BITS(&tp->th_opcode);
    printf(" %s",tok2str(op2str, "tftp-#%d", opcode));
    /* Bail if bogus opcode */

    switch (opcode) {

        case RRQ:
        break;

        case WRQ:
        break;

        case ACK:
        break;

        case DATA:
        break;

        case ERROR:
        break;

        default:
        /* We shouldn't get here */
        printf("(unknown #%d)", opcode);
        break;
    }
    return;
}

详细的可以查看tcpdump的源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值