IP协议结构

UDP协议结构

TFTP协议结构

TFTP端口

读写请求端口: 69

其他请求端口:1024~65535

主程序

/********************************************************************
*名称:menu
*参数:
*   none
*返回:
*   none
*功能:菜单命令
*********************************************************************/
void menu(){int num = 0;   //输入选项//显示菜单printf("\n");printf("**********************************************************************\n");printf("*                             Bootloader                             *\n");printf("*[1]Get MAC Address.                                                 *\n");printf("*[2]Download Kernel.                                                 *\n");printf("*[3]                                                                 *\n");printf("**********************************************************************\n");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 addrressunsigned char eh_src[6];   //source ethernet addresssunsigned 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 addressunsigned short arp_pro;   //format of protocol addressunsigned char  arp_hln;   //length of hardware addressunsigned char  arp_pln;   //length of protocol addressunsigned short arp_op;    //ARP/RARP operationunsigned char arp_sha[6];   //sender hardware addressunsigned char arp_spa[4];   //sender protocol addressunsigned char arp_tha[6];   //target hardware addressunsigned 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 lengthunsigned char  ip_tos;   //type of serviceunsigned short ip_len;   //total lengthunsigned short ip_id;    //identifiierunsigned short ip_off;   //flags and fragment offsetunsigned char  ip_ttl;   //time of liveunsigned char  ip_pro;   //protocolunsigned short ip_sum;   //header checksumunsigned char ip_src[IP_ADR_LEN];   //source addressunsigned 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 portunsigned short udp_dport;   //destination portunsigned short udp_len;     //lengthunsigned 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("\nIP  Address : ");for(i = 0; i < IP_ADR_LEN; i++){printf("%d.", ip_dst[i]);   //打印IP源地址}printf("\b \n");printf("MAC Address : ");for(i = 0; i < EH_ADR_LEN; i++){printf("%02X:", eh_dst[i]);   //打印MAC源地址}printf("\b \n");
}

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("\nTFTP Donwload Success!\n");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++] = '\0';   //结束标志for(i = 0; i < strlen(mode); i++){   //填充请求模式data[length++] = mode[i];}data[length++] = '\0';   //结束标志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);   //返回反码
}

转载于:https://www.cnblogs.com/d442130165/p/5013922.html

[国嵌攻略][068][tftp网络协议实现]相关推荐

  1. [国嵌攻略][139][输入子系统原理分析]

    输入子系统核心架构 1.设备驱动层 2.核心层 3.事件层 4.用户空间 输入设备注册 1.拿设备ID去匹配handler的ID,找到对应的handler(事件处理者) 最常用的handler是evd ...

  2. [国嵌攻略][080][无名管道通讯]

    通讯目的 1.数据传输 一个进程需要将数据发送给另外一个进程. 2.资源共享 多个进程之间共享同样的资源. 3.通知事件 一个进程需要向另外一个/组进程发送消息,通知它们发生了某事件. 4.进程控制 ...

  3. [国嵌攻略][085][共享内存通讯]

    共享内存 共享内存是IPC机制中的一种,它允许两个相关的进程访问同一段内存,这是传递数据的一种有效的方式. A.c #include <sys/types.h> #include < ...

  4. [国嵌攻略][084][信号同步编程]

    进程同步 一组并发进程进行相互合作.相互等待,使得各进程按一定的顺序执行的过程称为进程间的同步. 进程同步与进程互斥 进程同步问题的关键在于生产者不需要获取信号量,消费者不需要释放信号量,所以信号量的 ...

  5. [国嵌攻略][125][总线设备驱动模型]

    总线模型 随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求越来越高,2.4内核已经难以满足这些需求.为了适应这种形势的需要,从Linux2.6内核开始提供了全新的设备驱动模 ...

  6. [国嵌攻略][038][时钟初始化]

    时钟脉冲信号 按一定的电压幅度,一定的时间间隔连续发出的脉冲信号叫做时钟脉冲信号.用于给处理器和其他硬件提供时钟度量. 时钟脉冲频率 在单位时间内产生的时钟脉冲的个数叫做时间脉冲频率 时钟源分类 1. ...

  7. [国嵌攻略][054][NandFlash驱动设计_写]

    Nand Flash支持按页写和随机写两种方式,在下面实现的是按页写.闪存在写数据时,只能写入1,不能写入0,所以写函数必须和擦除函数一起使用,并且擦除函数是按块擦除. /************** ...

  8. 《恋爱攻略》用户隐私协议

    您在使用本公司的服务和产品<恋爱攻略>时,本公司可能会收集和使用您的相关信息.希望通过本<隐私政策>向您说明. 重要:TalkingData分析服务 TalkingData为移 ...

  9. 主程的晋升攻略(5):HTTP协议和二进制协议的对比

    在上一篇< 主程的晋升攻略(4):TCP.消息分包和协议设计>中谈了协议设计的一些话题,这里补充聊聊HTTP协议和二进制协议的对比. HTTP协议是一种文本协议,也是一种Name-Base ...

  10. 笔记本用无线路由器上网设置教程攻略

    http://www.33lc.com/article/2402.html [绿茶教程] 很多新买的笔记本的新用户都问笔记本如何无线上网,笔记本无线上网设置是怎么样的,那么到底怎样才能轻松实现笔记本无 ...

最新文章

  1. 10 个 Python 工程师,9 个不合格!
  2. 资源 |“从蒙圈到入坑”,推荐新一波ML、DL、RL以及数学基础等干货资源
  3. Sping面试题 Top 50
  4. 北斗导航 | 完全自主研发国产高端三维激光雷达助力中国测绘技术发展
  5. MoveAbsJ在使用时和MOVEJ有什么区别
  6. ECMAScript基础(三)-关键字
  7. java中继承applet类_java.applet.Applet类
  8. c语言内循环和外循环作用是什么,空调内循环和外循环的作用
  9. 操作系统-3.假设某多道程序设计系统中有供用户使用的内存100KB,打印机1台。系统采用可变分区方式管理内存:对打印机采用静态分配,并假设输入输出操作的时间忽略不计;采用最短剩余时间优先的进程调度算法
  10. 去除360安全卫士的广告弹窗(亲测有效)
  11. 学生专用计算机怎么没声音,班班通电脑没声音了
  12. 十分钟学会摩尔斯密码
  13. 关于阿里云主机数据丢失问题,是常态还是个例?如何保障数据安全?...
  14. 50条培养内心强大的励志语录
  15. html设置首缩选进两字符,首行缩进2字符怎么设置 css
  16. 马云给正在奋斗的人的经典语句
  17. 一篇文章构建你的 NodeJS 知识体系(W字长文)
  18. GShutDown:自动化关机鄙吝材
  19. 2JS-操作BOM对象
  20. mysql多条新增字段sql合并为一条新增

热门文章

  1. eclipse tomcat maven热部署
  2. win64 安装Oracle 11g
  3. Java 8 异步 API、循环、日期,用好提高生产力!
  4. 厉害了!如何在 Gihub 快速搜索开源项目?
  5. 我们精心整理的2019最新全栈资料!首次公布
  6. Instagram 使用 Python 的经验
  7. 一份阿里员工排查程序问题的命令列表
  8. 开发、运维、测试都要了解的测试技巧
  9. countable php,ThinkPHP容器之Countable巧用
  10. c mysql对时间加减_25.2.10. 日期和时间值的C API处理