• [国嵌攻略][068][tftp网络协议实现]


    IP协议结构

    UDP协议结构

    TFTP协议结构

    TFTP端口

    读写请求端口: 69

    其他请求端口:1024~65535

    主程序

    /********************************************************************
    *名称:menu
    *参数:
    *	none
    *返回:
    *	none
    *功能:菜单命令
    *********************************************************************/
    void menu(){
    	int num = 0;   //输入选项
    
    	//显示菜单
    	printf("
    ");
    	printf("**********************************************************************
    ");
    	printf("*                             Bootloader                             *
    ");
    	printf("*[1]Get MAC Address.                                                 *
    ");
    	printf("*[2]Download Kernel.                                                 *
    ");
    	printf("*[3]                                                                 *
    ");
    	printf("**********************************************************************
    ");
    	printf("Please Select: ");
    	
    	//选择菜单
    	scanf("%d", &num);
    	switch(num){
    		case 1:   //获取物理地址
    			send_arp_req();
    			isDisplay = 0;   //关闭显示菜单,等待获取物理地址
    			break;
    		
    		case 2:   //下载内核文件
    			send_tftp_read_req();
    			isDisplay = 0;   //关闭显示菜单,等待下载内核文件
    			break;
    			
    		default:
    			break;
    	}
    }
    

    网络头文件

    /********************************************************************
    *名称:net.h
    *作者:D
    *时间:2015.11.28
    *功能:网络协议头文件
    *********************************************************************/
    
    /********************************************************************
    *宏定义
    *********************************************************************/
    //MAC协议
    #define ETH_IP   0x0800  //IP
    #define ETH_ARP  0x0806  //ARP
    #define ETH_RARP 0x0805  //RARP
    
    //ARP协议
    #define ARP_ETH 0x0001   //Ethernet
    #define ARP_REQ 0x0001   //Request
    #define ARP_ACK 0x0002   //Acknowledge
    
    //IP协议
    #define IP_VHL 0x45     //version:4, header length:20byte
    #define IP_TOS 0x00     //type of service
    #define IP_ID  0x0000   //identifiier
    #define IP_OFF 0x4000   //flags and fragment offset
    #define IP_TTL 0xFF     //time of live
    #define IP_TCP 0x06     //TCP
    #define IP_UDP 0x11     //UDP
    #define IP_SUM 0x0000   //clear checksum
    #define IP_LEN 20       //header length
    
    //UDP协议
    #define UDP_TFTP_SRC 48915   //源端口
    #define UDP_TFTP_DST 69      //目的端口
    #define UDP_SUM 0            //假校验和
    
    //TFTP协议
    #define TFTP_RRQ 0x0001   //Read Request
    #define TFTP_WRQ 0x0002   //Write Request
    #define TFTP_DAT 0x0003   //File Data
    #define TFTP_ACK 0x0004   //Data Acknowledge
    #define TFTP_ERR 0x0005   //Error
    
    #define TFTP_DONWLOAD 0x31000000   //TFTP下载地址
    
    /*----------------------------------------分割线----------------------------------------*/
    
    #define EH_ADR_LEN 6       //物理地址长度
    #define IP_ADR_LEN 4       //协议地址长度
    #define ETH_PKT_MIN 64     //以太网帧最小长度
    #define ETH_PKT_MAX 1518   //以太网帧最大长度
    
    #define ETH_DAT_LEN  (ETH_PKT_MAX - sizeof(EHHDR))             //MAC数据部分长度
    #define IP_DAT_LEN   (ETH_DAT_LEN - sizeof(IPHDR))             //IP数据部分长度
    #define UDP_DAT_LEN  (IP_DAT_LEN - sizeof(UDPHDR))             //UDP数据部分长度
    #define TFTP_REQ_LEN (UDP_DAT_LEN - sizeof(TFTPHDR))           //TFTP请求数据部分长度
    #define TFTP_ACK_LEN (TFTP_REQ_LEN - sizeof(unsigned short))   //TFTP响应数据部分长度
    #define TFTP_DAT_LEN 512                                       //TFTP数据响应最大长度
    
    /*----------------------------------------分割线----------------------------------------*/
    
    #define HTONS(n) ( (((n)&0xFF00)>>8) | (((n)&0x00FF)<<8) )   //把unsigned short类型的主机序转换到网络序
    #define NTOHS(n) ( (((n)&0xFF00)>>8) | (((n)&0x00FF)<<8) )   //把unsigned short类型的网络序转换到主机序
    
    /********************************************************************
    *类型定义
    *********************************************************************/
    //MAC头部
    typedef struct ehhdr
    {
    	unsigned char eh_dst[6];   //destination ethernet addrress
    	unsigned char eh_src[6];   //source ethernet addresss
    	unsigned short eh_type;    //ethernet packet type
    }EHHDR;
    
    //MAC帧
    typedef struct ehPacket
    {
    	EHHDR ehhdr;             //MAC头部
    	
    	unsigned char data[ETH_DAT_LEN];   //MAC数据
    }EHPACKET;
    
    /*----------------------------------------分割线----------------------------------------*/
    
    //ARP头部
    typedef struct arphdr
    {
    	unsigned short arp_hrd;   //format of hardware address
    	unsigned short arp_pro;   //format of protocol address
    	
    	unsigned char  arp_hln;   //length of hardware address
    	unsigned char  arp_pln;   //length of protocol address
    	unsigned short arp_op;    //ARP/RARP operation
    
    	unsigned char arp_sha[6];   //sender hardware address
    	unsigned char arp_spa[4];   //sender protocol address
    	unsigned char arp_tha[6];   //target hardware address
    	unsigned char arp_tpa[4];   //target protocol address
    }ARPHDR;
    
    //ARP报文包
    typedef struct arpPacket
    {
    	EHHDR ehhdr;     //MAC头部
    	ARPHDR arphdr;   //ARP头部
    }ARPPACKET;
    
    /*----------------------------------------分割线----------------------------------------*/
    
    //IP头部
    typedef struct iphdr
    {
    	unsigned char  ip_vhl;   //version and header length
    	unsigned char  ip_tos;   //type of service
    	unsigned short ip_len;   //total length
    	
    	unsigned short ip_id;    //identifiier
    	unsigned short ip_off;   //flags and fragment offset
    	
    	unsigned char  ip_ttl;   //time of live
    	unsigned char  ip_pro;   //protocol
    	unsigned short ip_sum;   //header checksum
    	
    	unsigned char ip_src[IP_ADR_LEN];   //source address
    	unsigned char ip_dst[IP_ADR_LEN];   //destination address 
    }IPHDR;
    
    //IP报文包
    typedef struct ipPacket
    {
    	EHHDR ehhdr;             //MAC头部
    	IPHDR iphdr;             //IP头部
    	
    	unsigned char data[IP_DAT_LEN];   //IP数据
    }IPPACKET;
    
    /*----------------------------------------分割线----------------------------------------*/
    
    //UDP头部
    typedef struct udphdr
    {
    	unsigned short udp_sport;   //source port
    	unsigned short udp_dport;   //destination port
    	
    	unsigned short udp_len;     //length
    	unsigned short udp_sum;     //checksum
    }UDPHDR;
    
    //UDP报文包
    typedef struct udpPacket
    {
    	EHHDR ehhdr;             //MAC头部
    	IPHDR iphdr;             //IP头部
    	UDPHDR udphdr;           //UDP头部
    	
    	unsigned char data[UDP_DAT_LEN];   //UDP数据
    }UDPPACKET;
    
    /*----------------------------------------分割线----------------------------------------*/
    
    //TFTP头部
    typedef struct tftphdr
    {
    	unsigned short tftp_op;   //opcode
    }TFTPHDR;
    
    //TFTP请求包
    typedef struct tftpReqPacket
    {
    	EHHDR ehhdr;             //MAC头部
    	IPHDR iphdr;             //IP头部
    	UDPHDR udphdr;           //UDP头部
    	TFTPHDR tftphdr;         //TFTP头部
    	
    	unsigned char data[TFTP_REQ_LEN];   //TFTP数据
    }TFTPREQPACKET;
    
    //TFTP响应包
    typedef struct tftpAckPacket
    {
    	EHHDR ehhdr;             //MAC头部
    	IPHDR iphdr;             //IP头部
    	UDPHDR udphdr;           //UDP头部
    	TFTPHDR tftphdr;         //TFTP头部
    	
    	unsigned short blocknum;            //TFTP块号
    	unsigned char data[TFTP_ACK_LEN];   //TFTP数据
    }TFTPACKPACKET;
    

    网卡中断

    /********************************************************************
    *名称:dm9000_irq
    *参数:
    *	none
    *返回:
    *	none
    *功能:网卡中断服务
    *********************************************************************/
    void dm9000_irq(){
    	int state;             //接收状态
    	EHPACKET *eh_packet;   //MAC帧
    	
    	//接收网卡数据
    	state = rx_dm9000(packet);
    	
    	//处理网卡数据
    	if(state){   //如果接收成功,那么处理数据
    		//转换成MAC帧
    		eh_packet = (EHPACKET *)packet;
    		
    		//提供网络接口层服务
    		switch(NTOHS(eh_packet->ehhdr.eh_type)){   //判断网络层协议
    			case ETH_IP:    //IP协议
    				rece_ip_pro(eh_packet);
    				break;
    				
    			case ETH_ARP:   //ARP协议
    				rece_arp_pro(eh_packet);
    				break;
    				
    			default:
    				break;
    		}
    	}
    	
    	//清除外部中断请求
    	EINTPEND |= (1<<7);   //EINT8:cleard
    	
    	//清除中断源请求
    	SRCPND |= (1<<4);   //EINT4_7:cleard
    	
    	//清除中断请求
    	INTPND |= (1<<4);   //EINT4_7:cleard
    }
    

    ARP协议

    /********************************************************************
    *名称:arp.c
    *作者:D
    *时间:2015.11.26
    *功能:ARP协议
    *********************************************************************/
    
    /********************************************************************
    *头文件
    *********************************************************************/
    #include "net.h"
    
    /********************************************************************
    *全局变量声明
    *********************************************************************/
    //外部变量,定义在DM9000.c中
    extern unsigned char eh_src[EH_ADR_LEN];   //物理源地址
    extern unsigned char eh_dst[EH_ADR_LEN];   //物理目的地址
    extern unsigned char ip_src[IP_ADR_LEN];   //协议源地址
    extern unsigned char ip_dst[IP_ADR_LEN];   //协议目的地址
    
    extern int isDisplay;   //是否显示菜单标志
    
    /********************************************************************
    *函数原型声明
    *********************************************************************/
    void send_arp_req();
    void rece_arp_pro(ARPPACKET *arp_packet);
    void send_arp_ack(ARPPACKET *arp_packet);
    void rece_arp_ack(ARPPACKET *arp_packet);
    
    int create_arp_packet(ARPPACKET *arp_packet, unsigned short arp_op);
    int get_arp_dst_adr(ARPPACKET *arp_packet);
    void get_arp_src_adr(ARPPACKET *arp_packet);
    void put_arp_src_adr();
    
    /********************************************************************
    *名称:send_arp_req
    *参数:
    *	none
    *返回:
    *	none
    *功能:发送ARP请求包
    *********************************************************************/
    void send_arp_req(){
    	int length = 0;             //MAC帧长度
    	ARPPACKET arp_req_packet;   //ARP请求包
    	
    	//创建ARP请求包
    	length = create_arp_packet(&arp_req_packet, ARP_REQ);
    	
    	//发送ARP请求包
    	tx_dm9000(&arp_req_packet, length);
    }
    
    /********************************************************************
    *名称:rece_arp_pro
    *参数:
    *	arp_packet   ARP报文包
    *返回:
    *	none
    *功能:接收ARP协议
    *********************************************************************/
    void rece_arp_pro(ARPPACKET *arp_packet){
    	//提取目的地址
    	if( !get_arp_dst_adr(arp_packet) ){   //如果IP目的地址不匹配,那么返回
    		return ;
    	}
    	
    	//提供网络层服务
    	switch(NTOHS(arp_packet->arphdr.arp_op)){   //判断ARP操作码
    		case ARP_REQ:   //ARP请求
    			send_arp_ack(arp_packet);
    			break;
    			
    		case ARP_ACK:   //ARP响应
    			rece_arp_ack(arp_packet);
    			break;
    		
    		default:
    			break;
    	}
    }
    
    /********************************************************************
    *名称:send_arp_ack
    *参数:
    *	arp_packet   ARP报文包
    *返回:
    *	none
    *功能:发送ARP响应包
    *********************************************************************/
    void send_arp_ack(ARPPACKET *arp_packet){
    	int length = 0;             //MAC帧长度
    	ARPPACKET arp_ack_packet;   //ARP响应包
    	
    	//提取源地址
    	get_arp_src_adr(arp_packet);
    	
    	//创建ARP响应包
    	length = create_arp_packet(&arp_ack_packet, ARP_ACK);
    	
    	//发送ARP响应包
    	tx_dm9000(&arp_ack_packet, length);
    }
    
    /********************************************************************
    *名称:rece_arp_ack
    *参数:
    *	arp_packet   ARP报文包
    *返回:
    *	none
    *功能:接收ARP响应包
    *********************************************************************/
    void rece_arp_ack(ARPPACKET *arp_packet){
    	//提取源地址
    	get_arp_src_adr(arp_packet);
    	
    	//打印源地址
    	put_arp_src_adr();
    	
    	//打开显示菜单
    	isDisplay = 1;
    }
    
    /*----------------------------------------分割线----------------------------------------*/
    
    /********************************************************************
    *名称:create_arp_packet
    *参数:
    *	arp_packet   ARP报文包
    *	arp_op       ARP操作码
    *返回:
    *	length       MAC帧长度
    *功能:创建ARP报文包
    *********************************************************************/
    int create_arp_packet(ARPPACKET *arp_packet, unsigned short arp_op){
    	int length = 0;
    
    	//填充ARP头部
    	length = length + sizeof(ARPHDR);              //ARP报文长度
    	arp_packet->arphdr.arp_hrd = HTONS(ARP_ETH);   //硬件类型
    	arp_packet->arphdr.arp_pro = HTONS(ETH_IP);    //协议类型
    	arp_packet->arphdr.arp_hln = EH_ADR_LEN;       //MAC地址长度
    	arp_packet->arphdr.arp_pln = IP_ADR_LEN;       //IP地址长度
    	arp_packet->arphdr.arp_op  = HTONS(arp_op);    //操作类型
    	
    	memcpy(arp_packet->arphdr.arp_sha, eh_src, EH_ADR_LEN);   //MAC源地址
    	memcpy(arp_packet->arphdr.arp_spa, ip_src, IP_ADR_LEN);   //IP源地址
    	memcpy(arp_packet->arphdr.arp_tha, eh_dst, EH_ADR_LEN);   //MAC目的地址
    	memcpy(arp_packet->arphdr.arp_tpa, ip_dst, IP_ADR_LEN);   //IP目的地址
    	
    	//填充MAC头部
    	length = length + sizeof(EHHDR);                        //MAC帧长度
    	memcpy(arp_packet->ehhdr.eh_dst, eh_dst, EH_ADR_LEN);   //MAC目的地址
    	memcpy(arp_packet->ehhdr.eh_src, eh_src, EH_ADR_LEN);   //MAC源地址
    	arp_packet->ehhdr.eh_type = HTONS(ETH_ARP);             //MAC帧类型
    	
    	return length;
    }
    
    /********************************************************************
    *名称:get_arp_dst_adr
    *参数:
    *	arp_packet   ARP报文包
    *返回:
    *	return       1 匹配成功
    *	             0 匹配失败
    *功能:提取目的地址
    *********************************************************************/
    int get_arp_dst_adr(ARPPACKET *arp_packet){
    	unsigned char arp_ip_dst[IP_ADR_LEN];   //IP目的地址
    	
    	//提取IP目的地址
    	memcpy(arp_ip_dst, arp_packet->arphdr.arp_tpa, IP_ADR_LEN);
    	
    	//判断IP目的地址
    	if(memcmp(arp_ip_dst, ip_src, IP_ADR_LEN) != 0){   //如果目的地址不等于该主机IP地址,那么匹配失败
    		return 0;
    	}
    	
    	return 1;   //匹配成功
    }
    
    /********************************************************************
    *名称:get_arp_src_adr
    *参数:
    *	arp_packet   ARP报文包
    *返回:
    *	none
    *功能:提取源地址
    *********************************************************************/
    void get_arp_src_adr(ARPPACKET *arp_packet){
    	memcpy(eh_dst, arp_packet->arphdr.arp_sha, EH_ADR_LEN);   //提取MAC源地址,并写到目的地址
    	memcpy(ip_dst, arp_packet->arphdr.arp_spa, IP_ADR_LEN);   //提取IP源地址,并写到目的地址
    }
    
    /********************************************************************
    *名称:put_arp_src_adr
    *参数:
    *	none
    *返回:
    *	none
    *功能:打印源地址
    *********************************************************************/
    void put_arp_src_adr(){
    	int i;
    
    	printf("
    IP  Address : ");
    	for(i = 0; i < IP_ADR_LEN; i++){
    		printf("%d.", ip_dst[i]);   //打印IP源地址
    	}
    	printf(" 
    ");
    	
    	printf("MAC Address : ");
    	for(i = 0; i < EH_ADR_LEN; i++){
    		printf("%02X:", eh_dst[i]);   //打印MAC源地址
    	}
    	printf(" 
    ");
    }
    

    IP协议

    /********************************************************************
    *名称:ip.c
    *作者:D
    *时间:2015.11.28
    *功能:IP协议
    *********************************************************************/
    
    /********************************************************************
    *头文件
    *********************************************************************/
    #include "net.h"
    
    /********************************************************************
    *全局变量声明
    *********************************************************************/
    //外部变量,定义在DM9000.c中
    extern unsigned char ip_src[IP_ADR_LEN];   //IP源地址
    
    /********************************************************************
    *函数原型声明
    *********************************************************************/
    void rece_ip_pro(IPPACKET *ip_packet);
    int get_ip_dst_adr(IPPACKET *ip_packet);
    
    /********************************************************************
    *名称:rece_ip_pro
    *参数:
    *	ip_packet   IP报文包
    *返回:
    *	none
    *功能:接收IP协议
    *********************************************************************/
    void rece_ip_pro(IPPACKET *ip_packet){
    	//提取目的地址
    	if( !get_ip_dst_adr(ip_packet) ){   //如果IP目的地址不匹配,那么返回
    		return ;
    	}
    
    	//提供网络层服务
    	switch(ip_packet->iphdr.ip_pro){   //判断运输层协议
    		case IP_UDP:   //UDP协议
    			rece_udp_pro(ip_packet);
    			break;
    		
    		default:
    			break;
    	}
    }
    
    /********************************************************************
    *名称:get_ip_dst_adr
    *参数:
    *	ip_packet   IP报文包
    *返回:
    *	return      1 匹配成功
    *	            0 匹配失败
    *功能:提取目的地址
    *********************************************************************/
    int get_ip_dst_adr(IPPACKET *ip_packet){
    	unsigned char ip_dst_adr[IP_ADR_LEN];   //IP目的地址
    	
    	//提取IP目的地址
    	memcpy(ip_dst_adr, ip_packet->iphdr.ip_dst, IP_ADR_LEN);
    	
    	//判断IP目的地址
    	if(memcmp(ip_dst_adr, ip_src, IP_ADR_LEN) != 0){   //如果目的地址不等于该主机IP地址,那么匹配失败
    		return 0;
    	}
    	
    	return 1;   //匹配成功
    }
    

    UDP协议

    /********************************************************************
    *名称:udp.c
    *作者:D
    *时间:2015.11.30
    *功能:UDP协议
    *********************************************************************/
    
    /********************************************************************
    *头文件
    *********************************************************************/
    #include "net.h"
    
    /********************************************************************
    *函数原型声明
    *********************************************************************/
    void rece_udp_pro(UDPPACKET *udp_packet);
    
    /********************************************************************
    *名称:rece_udp_pro
    *参数:
    *	udp_packet   UDP报文包
    *返回:
    *	none
    *功能:接收UDP协议
    *********************************************************************/
    void rece_udp_pro(UDPPACKET *udp_packet){
    	//提供运输层服务
    	switch(NTOHS(udp_packet->udphdr.udp_dport)){   //判断应用层端口
    		case UDP_TFTP_SRC:   //TFTP协议源端口
    			rece_tftp_pro(udp_packet);
    			break;
    		
    		default:
    			break;
    	}
    }
    

    TFTP协议

    /********************************************************************
    *名称:tftp.c
    *作者:D
    *时间:2015.11.29
    *功能:TFTP协议
    *********************************************************************/
    
    /********************************************************************
    *头文件
    *********************************************************************/
    #include "net.h"
    
    /********************************************************************
    *全局变量声明
    *********************************************************************/
    //外部变量,定义在DM9000.c中
    extern unsigned char eh_src[EH_ADR_LEN];   //物理源地址
    extern unsigned char eh_dst[EH_ADR_LEN];   //物理目的地址
    extern unsigned char ip_src[IP_ADR_LEN];   //协议源地址
    extern unsigned char ip_dst[IP_ADR_LEN];   //协议目的地址
    
    extern int isDisplay;   //是否显示菜单标志
    
    unsigned short reqblknum;       //TFTP请求块号
    unsigned char *tftp_download;   //TFTP下载地址
    
    /********************************************************************
    *函数原型声明
    *********************************************************************/
    void send_tftp_read_req();
    void rece_tftp_pro(TFTPACKPACKET *tftp_packet);
    void rece_tftp_data_ack(TFTPACKPACKET *tftp_packet);
    
    int get_tftp_data_ack(TFTPACKPACKET *tftp_packet, unsigned short *blocknum, unsigned short *udpdport);
    int create_tftp_req_packet(TFTPREQPACKET *tftp_packet, unsigned short tftp_op, const char *filename, const char *mode);
    int create_tftp_ack_packet(TFTPACKPACKET *tftp_packet, unsigned short tftp_op, unsigned short blocknum, unsigned short udpdport);
    unsigned short checksum(unsigned short* iphdr, int size);
    
    /********************************************************************
    *名称:send_tftp_read_req
    *参数:
    *	none
    *返回:
    *	none
    *功能:发送TFTP读请求包
    *********************************************************************/
    void send_tftp_read_req(){
    	int length = 0;                  //MAC帧长度
    	TFTPREQPACKET tftp_req_packet;   //TFTP请求包
    	
    	//设置TFTP请求块号
    	reqblknum = 1;
    	
    	//设置TFTP下载地址
    	tftp_download = (unsigned char *)TFTP_DONWLOAD;
    
    	//创建TFTP读请求包
    	length = create_tftp_req_packet(&tftp_req_packet, TFTP_RRQ, "boot.bin", "octet");
    	
    	//发送TFTP读请求包
    	tx_dm9000(&tftp_req_packet, length);
    }
    
    /********************************************************************
    *名称:rece_tftp_pro
    *参数:
    *	rece_tftp_pro   TFTP响应包
    *返回:
    *	none
    *功能:接收TFTP协议
    *********************************************************************/
    void rece_tftp_pro(TFTPACKPACKET *tftp_packet){
    	//提供应用层服务
    	switch(NTOHS(tftp_packet->tftphdr.tftp_op)){   //判断TFTP操作码
    		case TFTP_DAT:   //TFTP文件数据
    			rece_tftp_data_ack(tftp_packet);
    			break;
    		
    		default:
    			break;
    	}
    }
    
    /********************************************************************
    *名称:rece_tftp_data_ack
    *参数:
    *	tftp_packet   TFTP响应包
    *返回:
    *	none
    *功能:接收TFTP数据响应包
    *********************************************************************/
    void rece_tftp_data_ack(TFTPACKPACKET *tftp_packet){
    	int length = 0;                  //MAC帧长度
    	unsigned short blocknum = 0;     //TFTP块号
    	unsigned short udpdport = 0;     //UDP目的端口
    	TFTPACKPACKET tftp_ack_packet;   //TFTP响应包
    	
    	//提取数据响应包
    	if( !get_tftp_data_ack(tftp_packet, &blocknum, &udpdport) ){   //如果提取失败,那么返回
    		return ;
    	}
    	
    	//创建TFTP响应包
    	length  = create_tftp_ack_packet(&tftp_ack_packet, TFTP_ACK, blocknum, udpdport);
    	
    	//发送TFTP响应包
    	tx_dm9000(&tftp_ack_packet, length);
    }
    
    /*----------------------------------------分割线----------------------------------------*/
    
    /********************************************************************
    *名称:get_tftp_data_ack
    *参数:
    *	tftp_packet   TFTP响应包
    *	blocknum      TFTP块号
    *	udpdport      UDP目的端口
    *返回:
    *	return        1 提取成功
    *	              0 提取失败
    *功能:提取TFTP数据响应包
    *********************************************************************/
    int get_tftp_data_ack(TFTPACKPACKET *tftp_packet, unsigned short *blocknum, unsigned short *udpdport){
    	int i;
    	int length = 0;   //TFTP数据长度
    
    	//提取TFTP响应块号
    	*blocknum = NTOHS(tftp_packet->blocknum);
    	if(*blocknum != reqblknum){   //如果TFTP块号不等于请求块号,那么返回
    		return 0;
    	}
    	
    	//增加TFTP请求块号
    	reqblknum++;
    	
    	//提取UDP目的端口
    	*udpdport = NTOHS(tftp_packet->udphdr.udp_sport);
    	
    	//计算TFTP数据长度
    	length = NTOHS(tftp_packet->udphdr.udp_len);   //提取UDP报文长度
    	length = length - sizeof(UDPHDR);              //计算TFTP报文长度
    	length = length - sizeof(TFTPHDR);             //计算TFTP数据长度
    	length = length - sizeof(unsigned short);
    	
    	//提取TFTP响应数据
    	for(i = 0; i < length; i++){
    		*(tftp_download++) = tftp_packet->data[i];   //下载到指定内存地址
    	}
    	
    	//判断最后数据响应
    	if(length < TFTP_DAT_LEN){   //如果数据长度小于最大长度,那么发出最后响应包
    		printf("
    TFTP Donwload Success!
    ");
    		isDisplay = 1;   //打开显示菜单
    	}
    	
    	return 1;
    }
    
    /********************************************************************
    *名称:create_tftp_req_packet
    *参数:
    *	tftp_packet   TFTP请求包
    *	tftp_op       TFTP操作码
    *	filename      请求文件名
    *	mode          请求模式
    *返回:
    *	length        MAC帧长度
    *功能:创建TFTP请求包
    *********************************************************************/
    int create_tftp_req_packet(TFTPREQPACKET *tftp_packet, unsigned short tftp_op, const char *filename, const char *mode){
    	int i;
    	int length = 0;
    	unsigned char data[TFTP_REQ_LEN];   //TFTP数据
    	unsigned short *iphdr;              //IP起始地址
    	unsigned short chksum;              //IP头校验和
    
    	//填充TFTP数据
    	for(i = 0; i < strlen(filename); i++){   //填充请求文件名
    		data[length++] = filename[i];
    	}
    	data[length++] = '';   //结束标志
    	
    	for(i = 0; i < strlen(mode); i++){   //填充请求模式
    		data[length++] = mode[i];
    	}
    	data[length++] = '';   //结束标志
    
    	memcpy(tftp_packet->data, data, length);   //填充TFTP数据
    
    	//填充TFTP头部
    	length = length + sizeof(TFTPHDR);                //TFTP报文长度
    	tftp_packet->tftphdr.tftp_op = HTONS(tftp_op);    //填充操作码
    
    	//填充UDP头部
    	length =length + sizeof(UDPHDR);                       //UDP报文长度
    	tftp_packet->udphdr.udp_sport = HTONS(UDP_TFTP_SRC);   //UDP源端口
    	tftp_packet->udphdr.udp_dport = HTONS(UDP_TFTP_DST);   //UDP目的端口
    	tftp_packet->udphdr.udp_len = HTONS(length);           //UDP报文长度
    	tftp_packet->udphdr.udp_sum = HTONS(UDP_SUM);          //UDP头假校验和
    
    	//填充IP头部
    	length = length + sizeof(IPHDR);             //IP报文长度
    	tftp_packet->iphdr.ip_vhl = IP_VHL;          //版本号:IPv4,协议头长度:20字节
    	tftp_packet->iphdr.ip_tos = IP_TOS;          //普通服务类型
    	tftp_packet->iphdr.ip_len = HTONS(length);   //IP报文长度
    	
    	tftp_packet->iphdr.ip_id = HTONS(IP_ID);    //标识符
    	tftp_packet->iphdr.ip_off = HTONS(IP_OFF);  //标记
    	
    	tftp_packet->iphdr.ip_ttl = IP_TTL;   //生存时间
    	tftp_packet->iphdr.ip_pro = IP_UDP;   //UDP协议
    	
    	memcpy(tftp_packet->iphdr.ip_src, ip_src, IP_ADR_LEN);   //IP源地址
    	memcpy(tftp_packet->iphdr.ip_dst, ip_dst, IP_ADR_LEN);   //IP目的地址
    	
    	tftp_packet->iphdr.ip_sum = HTONS(IP_SUM);          //清零校验和
    	iphdr = (unsigned short *)&(tftp_packet->iphdr);    //获取IP指针
    	chksum = checksum(iphdr, IP_LEN);                   //计算校验和
    	tftp_packet->iphdr.ip_sum = chksum;                 //头部校验和,注意不需要网络序转换,计算的本来就是网络序的校验和
    	
    	//填充MAC头部
    	length = length + sizeof(EHHDR);                         //MAC帧长度
    	memcpy(tftp_packet->ehhdr.eh_dst, eh_dst, EH_ADR_LEN);   //MAC目的地址
    	memcpy(tftp_packet->ehhdr.eh_src, eh_src, EH_ADR_LEN);   //MAC源地址
    	tftp_packet->ehhdr.eh_type = HTONS(ETH_IP);              //MAC帧类型
    	
    	return length;
    }
    
    
    /********************************************************************
    *名称:create_tftp_ack_packet
    *参数:
    *	tftp_packet   TFTP响应包
    *	tftp_op       TFTP操作码
    *	blocknum      TFTP块号
    *	udpdport      UDP目的端口
    *返回:
    *	length        MAC帧长度
    *功能:创建TFTP响应包
    *********************************************************************/
    int create_tftp_ack_packet(TFTPACKPACKET *tftp_packet, unsigned short tftp_op, unsigned short blocknum, unsigned short udpdport){
    	int i;
    	int length = 0;          //数据长度
    	unsigned short *iphdr;   //IP起始地址
    	unsigned short chksum;   //IP头校验和
    
    	//填充TFTP块号
    	length = length + sizeof(unsigned short);   //TFTP数据长度
    	tftp_packet->blocknum = HTONS(blocknum);    //填充TFTP块号
    
    	//填充TFTP头部
    	length = length + sizeof(TFTPHDR);               //TFTP报文长度
    	tftp_packet->tftphdr.tftp_op = HTONS(tftp_op);   //填充操作码
    
    	//填充UDP头部
    	length =length + sizeof(UDPHDR);                       //UDP报文长度
    	tftp_packet->udphdr.udp_sport = HTONS(UDP_TFTP_SRC);   //UDP源端口
    	tftp_packet->udphdr.udp_dport = HTONS(udpdport);       //UDP目的端口
    	tftp_packet->udphdr.udp_len = HTONS(length);           //UDP数据包长度
    	tftp_packet->udphdr.udp_sum = HTONS(UDP_SUM);          //UDP头假校验和
    
    	//填充IP头部
    	length = length + sizeof(IPHDR);             //IP报文长度
    	tftp_packet->iphdr.ip_vhl = IP_VHL;          //版本号:IPv4,协议头长度:20字节
    	tftp_packet->iphdr.ip_tos = IP_TOS;          //普通服务类型
    	tftp_packet->iphdr.ip_len = HTONS(length);   //IP报文长度
    	
    	tftp_packet->iphdr.ip_id = HTONS(IP_ID);    //标识符
    	tftp_packet->iphdr.ip_off = HTONS(IP_OFF);  //标记
    	
    	tftp_packet->iphdr.ip_ttl = IP_TTL;   //生存时间
    	tftp_packet->iphdr.ip_pro = IP_UDP;   //UDP协议
    	
    	memcpy(tftp_packet->iphdr.ip_src, ip_src, IP_ADR_LEN);   //IP源地址
    	memcpy(tftp_packet->iphdr.ip_dst, ip_dst, IP_ADR_LEN);   //IP目的地址
    	
    	tftp_packet->iphdr.ip_sum = HTONS(IP_SUM);          //清零校验和
    	iphdr = (unsigned short *)&(tftp_packet->iphdr);    //获取IP地址
    	chksum = checksum(iphdr, IP_LEN);                   //计算校验和
    	tftp_packet->iphdr.ip_sum = chksum;                 //头部校验和,注意不需要网络序转换,计算的本来就是网络序的校验和
    	
    	//填充以太网帧头部
    	length = length + sizeof(EHHDR);                         //MAC帧长度
    	memcpy(tftp_packet->ehhdr.eh_dst, eh_dst, EH_ADR_LEN);   //MAC目的地址
    	memcpy(tftp_packet->ehhdr.eh_src, eh_src, EH_ADR_LEN);   //MAC源地址
    	tftp_packet->ehhdr.eh_type = HTONS(ETH_IP);              //MAC帧类型
    	
    	return length;
    }
    
    /********************************************************************
    *名称:checksum
    *参数:
    *	iphdr    IP起始地址
    *	size     IP头部长度
    *返回:
    *	chksum   IP头校验和
    *功能:计算IP头校验和
    *********************************************************************/
    unsigned short checksum(unsigned short* iphdr, int size){
        unsigned long chksum = 0;
    	
        while(size > 1){   //16位二进制求和
            chksum += *iphdr++;
            size -= sizeof(unsigned short);
        }
        if(size == 1){    //如果头部长度为奇数,那么再加上最后8位
            chksum += *((unsigned char*)iphdr);
        }
    	
        chksum = (chksum>>16) + (chksum&0xFFFF);   //加上进位
        chksum += (chksum>>16);                    //加上进位产生的进位
    	
        return (unsigned short)(~chksum);   //返回反码
    }
    
  • 相关阅读:
    Python基础之subprocess
    Python基础之读取ini文件
    Python如何将py文件打包成exe
    C++第四十一篇 -- 安装成功的第一个驱动文件
    C++第四十篇 -- 研究一下Windows驱动开发(三)-- NT式驱动的基本结构
    C++第三十九篇 -- 研究一下Windows驱动开发(二)-- 驱动程序中重要的数据结构
    C++第三十八篇 -- 研究一下Windows驱动开发(二)--WDM式驱动的加载
    C++第三十七篇 -- 调试驱动程序
    iis提示“另一个程序正在使用此文件,进程无法访问。(异常来自HRESULT:0x80070020) ”解决办法
    Serv-U无法上传“中文文件夹”的问题(没有权限)
  • 原文地址:https://www.cnblogs.com/d442130165/p/5013922.html
Copyright © 2020-2023  润新知