移植 tftp 客户端

来源:互联网 发布:微信显示网络出错1003 编辑:程序博客网 时间:2024/05/16 18:20

tftp网络协议分析

可以通过tftp下载Linux内核和程序文件到开发板运行。

tftp交互过程
这里写图片描述

tftp报文格式
每个包的数据不能超过512字节。
tftp协议属于udp协议,udp协议属于ip协议。
这里写图片描述

tftp网络协议的实现

arp.h

typedef unsigned int   u32;typedef unsigned short u16;typedef unsigned char  u8;typedef struct eth_hdr{    u8 d_mac[6];    u8 s_mac[6];    u16 type;}ETH_HDR;typedef struct arp_hdr{    ETH_HDR ethhdr;    u16 hwtype;    u16 protocol;    u8 hwlen;    u8 protolen;    u16 opcode;    u8 smac[6];    u8 sipaddr[4];    u8 dmac[6];    u8 dipaddr[4];}ARP_HDR;typedef struct ip_hdr{    ETH_HDR ethhdr;    u8 vhl;    u8 tos;    u16 len;    u16 ipid;    u16 ipoffset;    u8 ttl;    u8 proto;    u16 ipchksum;    u8 srcipaddr[4];    u8 destipaddr[4];}IP_HDR;typedef struct udp_hdr{    IP_HDR iphdr;    u16 sport;    u16 dport;    u16 len;    u16 udpchksum;}UDP_HDR;typedef struct tftp_package{    u16 opcode;    u16 blocknum;    u8 data[0]; }TFTP_PAK;ARP_HDR arpbuf;#define PROTO_ARP 0x0806#define PROTO_IP 0x0800#define PROTO_UDP 0x11extern u8 host_mac_addr[6];extern u8 mac_addr[6];extern u8 ip_addr[4];extern u8 host_ip_addr[4];extern u16 packet_len;

arp.c

#include "arp.h"#define HON(n) ((((u16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))/*1.发送arp请求包*/void arp_request(){     /*1.构成arp请求包*/     memcpy(arpbuf.ethhdr.d_mac,host_mac_addr,6);     memcpy(arpbuf.ethhdr.s_mac,mac_addr,6);     arpbuf.ethhdr.type = HON(0x0806);     arpbuf.hwtype = HON(1);     arpbuf.protocol = HON(0x0800);     arpbuf.hwlen = 6;     arpbuf.protolen = 4;     arpbuf.opcode = HON(1);     memcpy(arpbuf.smac,mac_addr,6);     memcpy(arpbuf.sipaddr,ip_addr,4);     memcpy(arpbuf.dipaddr,host_ip_addr,4);     packet_len = 14+28;     /*2.调用dm9000发送函数,发送应答包*/        dm9000_tx(&arpbuf,packet_len);}/*2.解析arp应答包,提取mac*/u8 arp_process(u8 *buf, u32 len){    u32 i;    ARP_HDR *arp_p = (ARP_HDR *)buf;    if (packet_len<28)        return 0;    switch (HON(arp_p->opcode))    {        case 2: /*arp响应包*/            memcpy(host_ip_addr,arp_p->sipaddr,4);            printf("host ip is : ");            for(i=0;i<4;i++)               printf("%03d ",host_ip_addr[i]);            printf("\n\r");            memcpy(host_mac_addr,arp_p->smac,6);            printf("host mac is : ");            for(i=0;i<6;i++)            printf("%02x ",host_mac_addr[i]);            printf("\n\r");            break;        case 1: /*arp请求包*/        /*发送arp响应包*/            memcpy(arpbuf.ethhdr.d_mac,arp_p->smac,6);            memcpy(arpbuf.ethhdr.s_mac,mac_addr,6);            arpbuf.ethhdr.type = HON(0x0806);            arpbuf.hwtype = HON(1);            arpbuf.protocol = HON(0x0800);            arpbuf.hwlen = 6;            arpbuf.protolen = 4;            arpbuf.opcode = HON(2);            memcpy(arpbuf.smac,mac_addr,6);            memcpy(arpbuf.sipaddr,ip_addr,4);            memcpy(arpbuf.dmac,arp_p->smac,6);            memcpy(arpbuf.dipaddr,arp_p->sipaddr,4);            packet_len = 14+28;         /*2.调用dm9000发送函数,发送应答包*/               dm9000_tx(&arpbuf,packet_len);                       break;     }}void udp_process(u8* buf, u32 len){     UDP_HDR *udphdr = (UDP_HDR *)buf;     tftp_process(buf,len,HON(udphdr->sport));      }void ip_process(u8 *buf, u32 len){     IP_HDR *p = (IP_HDR *)buf;      switch(p->proto)     {        case PROTO_UDP:            udp_process(buf,len);            break;        default:            break;       }}void net_handle(u8 *buf, u32 len){     ETH_HDR *p = (ETH_HDR *)buf;     switch (HON(p->type))     {        case PROTO_ARP:            arp_process(buf,len);            break;        case PROTO_IP:            ip_process(buf,len);            break;        default:            break;     }}void dm9000_arp(){    while(1)        arp_request();  }

tftp.c

#include "string.h"#include "arp.h"u8 sendbuf[1024];u8* tftp_down_addr = 0x31000000;u16 serverport = 0;u16 curblock = 1;#define HON(n) ((((u16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))u16 checksum(u8 *ptr, int len){    u32 sum = 0;    u16 *p = (u16 *)ptr;    while (len > 1)    {        sum += *p++;        len -= 2;    }    if(len == 1)        sum += *(u8 *)p;    while(sum>>16)        sum = (sum&0xffff) + (sum>>16);    return (u16)((~sum)&0xffff);}void tftp_send_request(const char *filename){    u8 *ptftp = &sendbuf[200];    u32 tftp_len = 0;    UDP_HDR *udphdr;    u8 *iphdr;    ptftp[0] = 0x00;    ptftp[1] = 0x01;    tftp_len += 2 ;    sprintf(&ptftp[tftp_len],"%s",filename);    tftp_len += strlen(filename);    ptftp[tftp_len] = '\0';    tftp_len += 1;    sprintf(&ptftp[tftp_len],"%s","octet");    tftp_len += strlen("octect");    ptftp[tftp_len] = '\0';    tftp_len += 1;    udphdr = ptftp-sizeof(UDP_HDR);    iphdr =  ptftp-sizeof(UDP_HDR)+ sizeof(ETH_HDR);    /*UDP帧头信息*/    udphdr->sport = HON(48915);    udphdr->dport = HON(69);    udphdr->len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(IP_HDR));    udphdr->udpchksum = 0x00;    /*IP帧头信息*/    udphdr->iphdr.vhl = 0x45;    udphdr->iphdr.tos = 0x00;    udphdr->iphdr.len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(ETH_HDR));    udphdr->iphdr.ipid = HON(0x00);    udphdr->iphdr.ipoffset = HON(0x4000);    udphdr->iphdr.ttl = 0xff;    udphdr->iphdr.proto = 17;    memcpy(udphdr->iphdr.srcipaddr,ip_addr,4);    memcpy(udphdr->iphdr.destipaddr,host_ip_addr,4);    udphdr->iphdr.ipchksum = 0;    udphdr->iphdr.ipchksum = checksum(iphdr,20);    memcpy(udphdr->iphdr.ethhdr.s_mac,mac_addr,6);    memcpy(udphdr->iphdr.ethhdr.d_mac,host_mac_addr,6);    udphdr->iphdr.ethhdr.type = HON(PROTO_IP);    dm9000_tx((u32 *)udphdr,sizeof(UDP_HDR)+tftp_len);}void tftp_send_ack(u16 blocknum){    u8 *ptftp = &sendbuf[200];    u32 tftp_len = 0;    UDP_HDR *udphdr;    u8 *iphdr;    ptftp[0] = 0x00;    ptftp[1] = 0x04;    tftp_len += 2 ;    ptftp[2] = (blocknum&0xff00)>>8;    ptftp[3] = (blocknum&0xff);    tftp_len += 2 ;    udphdr = ptftp-sizeof(UDP_HDR);    iphdr =  ptftp-sizeof(UDP_HDR)+ sizeof(ETH_HDR);    /*UDP帧头信息*/    udphdr->sport = HON(48915);    udphdr->dport = HON(serverport);    udphdr->len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(IP_HDR));    udphdr->udpchksum = 0x00;    /*IP帧头信息*/    udphdr->iphdr.vhl = 0x45;    udphdr->iphdr.tos = 0x00;    udphdr->iphdr.len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(ETH_HDR));    udphdr->iphdr.ipid = HON(0x00);    udphdr->iphdr.ipoffset = HON(0x4000);    udphdr->iphdr.ttl = 0xff;    udphdr->iphdr.proto = 17;    memcpy(udphdr->iphdr.srcipaddr,ip_addr,4);    memcpy(udphdr->iphdr.destipaddr,host_ip_addr,4);    udphdr->iphdr.ipchksum = 0;    udphdr->iphdr.ipchksum = checksum(iphdr,20);    memcpy(udphdr->iphdr.ethhdr.s_mac,mac_addr,6);    memcpy(udphdr->iphdr.ethhdr.d_mac,host_mac_addr,6);    udphdr->iphdr.ethhdr.type = HON(PROTO_IP);    dm9000_tx((u32 *)udphdr,sizeof(UDP_HDR)+tftp_len);}void tftp_process(u8 *buf, u32 len, u16 port){     u32 i;     u32 tftp_len;     serverport = port;     TFTP_PAK *ptftp = buf + sizeof(UDP_HDR);     tftp_len = len - sizeof(UDP_HDR);     if(HON(ptftp->opcode) == 3)     {         if (HON(ptftp->blocknum) == curblock)         {              for (i = 0;i<(tftp_len-4);i++)              {                  *(tftp_down_addr) = *(ptftp->data+i);              }               tftp_send_ack(HON(ptftp->blocknum));              curblock++;              if ((tftp_len-4)<512)                  curblock = 1;         }    }}
原创粉丝点击