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 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("\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); //返回反码
}

[国嵌攻略][068][tftp网络协议实现]的更多相关文章

  1. [国嵌攻略][090][linux网络编程模型]

    编程模型 Socket的实质就是一个接口,利用该接口,用户在使用不同的网络协议时,操作函数得以统一.而针对不同协议的差异性操作,则交给了Socket去自行解决. TCP编程模型 UDP编程模型

  2. [国嵌攻略][067][tftp协议分析]

    TFTP作用 用于网络下载,TFTP客户机在TFTP服务器中下载文件. TFTP交换过程 1.配置TFTP服务器 vim /etc/xinetd.d/tftp 2.交换过程 客户端发请求包到服务器 服 ...

  3. [国嵌攻略][092][UDP网络程序设计]

    server.c #include <sys/socket.h> #include <netinet/in.h> #include <strings.h> #inc ...

  4. [国嵌攻略][091][TCP网络程序设计]

    server.c #include <sys/socket.h> #include <netinet/in.h> #include <strings.h> #inc ...

  5. [国嵌攻略][099][Linux内核配置与编译]

    为什么要配置内核 基于硬件和软件的需求选出需要的功能,去掉不要的功能. 内核配置的方法 make config:基于文本交互的配置. make menuconfig:基于图形菜单的配置. make m ...

  6. [国嵌攻略][098][Linux内核简介]

    Linux系统架构 1.用户空间:应用程序.C函数库 2.内核空间:系统调用接口.内核.体系结构相关代码 Linux系统利用处理器不同的工作模式,使用其中的两个级别分别来运行Linux内核与应用程序, ...

  7. [国嵌攻略][066][ARP协议实现]

    以太网通讯 在计算机网络中,数据发送的过程就是把数据按照各层协议层层封装的过程.在这个过程中,最终要使用的协议通常是以太网协议(数据链路层协议). 以太网包格式 目的MAC地址:接收者的物理地址(6字 ...

  8. [国嵌攻略][162][USB协议分析]

    USB设备逻辑结构 在USB设备的逻辑组织中,包含设备.配置.接口和端点4个层次.设备通常有一个或多个配置,配置通常有一个或多个接口,接口通常有零个或多个端点. USB设备描述符 当我们把USB设备( ...

  9. [国嵌攻略][179][OpenSSL加密系统]

    未加密传输的安全弊端 如果在网络传输中没有加密,就是以明文传输.传输的数据可以被抓包软件直接截获,并能读取里面的数据. 加密基本原理 1.对称加密 2.非对称加密 2.1.公钥私钥 公钥和私密要配对. ...

随机推荐

  1. 英雄联盟LOL用什么语言写的?

    是用openGL开发的 开发语言是c/c++ 客户端是一个.net的web界面

  2. Error in .Call.graphics(C_palette2, .Call(C_palette2, NULL)) : invalid graphics state

    在调用ggplpt2包画图时,出现错误 Error in .Call.graphics(C_palette2, .Call(C_palette2, NULL)) : invalid graphics ...

  3. php+中文分词scws+sphinx+mysql打造千万级数据全文搜索

    转载自:http://blog.csdn.net/nuli888/article/details/51892776 Sphinx是由俄罗斯人Andrew Aksyonoff开发的一个全文检索引擎.意图 ...

  4. 如何高逼格读取Web.config中的AppSettings

    http://edi.wang/post/2015/4/22/how-to-read-webconfig-appsettings-with-bigiblity 先插句题外话,下版本的ASP.NET貌似 ...

  5. css-display

    1. none:隐藏对象.与visibility属性的hidden值不同,其不为被隐藏的对象保留其物理空间 2. inline:指定对象为内联元素. 3. block:指定对象为块元素. 4. inl ...

  6. python基础(五)列表,元组,集合

    列表 在python中是由数个有序的元素组成的数据结构,每一个元素对应一个index索引来隐式标注元素在列表中的位置.是python中最常用的一种数据类型.需要注意的是列表中可以有重复相同的数据. 列 ...

  7. I/O模型详细解析

    内核空间和用户空间:由于操作系统都包括内核空间和用户空间(或者说内核态和用户态),内核空间主要存放的是内核代码和数据,是供系统进程使用的空间.而用户空间主要存放的是用户代码和数据,是供用户进程使用的空 ...

  8. Windows程序设计笔记(二) 关于编写简单窗口程序中的几点疑惑

    在编写窗口程序时主要是5个步骤,创建窗口类.注册窗口类.创建窗口.显示窗口.消息环的编写.对于这5个步骤为何要这样写,当初我不是太理解,学习到现在有些问题我基本上已经找到了答案,同时对于Windows ...

  9. Core Animation文档翻译 (第一篇)

    Core Animation 文档翻译(第一篇) 前言 作为iOS 开发,官方文档的阅读是很有必要的,值此周末便写下此文.作为iOS 实际经验3年的开发,之前有阅读并实践过经典的<iOS核心动画 ...

  10. (转)Linux下运行python

    原文: http://blog.csdn.net/jackywgw/article/details/48847187 在linux命令行下运行python,可以直接输出hello world jack ...