[国嵌攻略][068][tftp网络协议实现]
IP协议结构
UDP协议结构
TFTP协议结构
TFTP端口
读写请求端口: 69
其他请求端口:1024~65535
主程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /******************************************************************** *名称: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 ; } } |
网络头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | /******************************************************************** *名称: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; |
网卡中断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /******************************************************************** *名称: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协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | /******************************************************************** *名称: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协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | /******************************************************************** *名称: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协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /******************************************************************** *名称: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协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | /******************************************************************** *名称: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); //返回反码 } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术