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