TFTP网络协议分析---15
TFTP网络协议分析
周学伟
文档说明:所有函数都依托与两个出口,发送和接收。
1:作为发送时,要完成基于TFTP协议下的文件传输,但前提是知道木的PC机的MAC地址,因为当发送TFTP请求包时必须提供目的主机的MAC地址。则提供串口srcureCRT控制台,首先进行ARP请求包的发送,收到来自客户端的ARP应答包时,提取出目的主机的MAC地址,然后在发送TFTP请求包,等到目的主机返回数据报文后,文件传输即可开始,此过程,可用wireshark抓包工具进行检测。
2:作为接收时,可在DM9000网卡芯片提供的中断标号初进行等待,当网卡收到相应的数据包时,即可让函数进行处理。
1定义帧头的结构体
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef struct eth_hdr
{
u8 d_mac[6];
u8 s_mac[6];
u16 type;
}ETH_HDR;
ARP数据包的格式
以太网的目的地址d_mac |
以太网的源地址s_mac |
帧类型 type |
硬件类型 hwtype; |
协议类型 protocol |
硬件地址长度 hwlen |
协议地址长度 protolen |
Opcode 1:请求包 2:应答包 |
发送端的以太网地址smac[6] |
发送端的IP地址 sipaddr[4] |
目的以太网地址 dmac[6]; |
目的IP地址 dipaddr[4]
|
typedef struct arp_hdr
{
ETH_HDR ethhdr;
u16 hwtype;
u16 protocol;
u8 hwlen;
u8 protolen;
u16 opcode;
u8 smac[6];
u8 sipaddr[4];
u8 dmac[6];
u8 dipaddr[4];
}ARP_HDR;
ARP_HDR arpbuf;
IP协议的报文格式
版本 vhl |
报文长度 vhl |
服务级别 tos |
报文长度 len |
标识 ipid |
标志 ipoffset |
生命时间 ttl |
用户协议 proto |
报文校验 ipchksum |
源IP地址 srcipaddr[4] |
目的IP地址 u8 destipaddr[4] |
数据
|
typedef struct ip_hdr
{
ETH_HDR ethhdr;
u8 vhl;
u8 tos;
u16 len;
u16 ipid;
u16 ipoffset;
u8 ttl;
u8 proto;
u16 ipchksum;
u8 srcipaddr[4];
u8 destipaddr[4];
}IP_HDR;
UDP协议格式
16 位源端口号 |
16位目的端口号 |
16位UDP长度 |
16位UDP检验 |
数据(如果有) |
typedef struct udp_hdr
{
IP_HDR iphdr;
u16 sport;
u16 dport;
u16 len;
u16 udpchksum;
}UDP_HDR;
TFTP报文格式
IP首部 |
UDP首部 |
opcode |
文件名 |
0(默认) |
传输模式 |
0(默认) |
|
|
操作码 opcode |
快编码 blocknum |
数据 data[0] |
typedef struct tftp_package
{
u16 opcode;
u16 blocknum;
u8 data[0];
}TFTP_PAK;
#define PROTO_ARP 0x0806
#define PROTO_IP 0x0800
#define PROTO_UDP 0x11
u8 buffer[1500];
u8 host_mac_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
u8 mac_addr[6] = {9,8,7,6,5,4};
u8 ip_addr[4] = {192,168,1,30};
u8 host_ip_addr[4] = {192,168,1,100};
u16 packet_len;
2进入ARP.C中处理
#include "arp.h"
#define HON(n) ((((u16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))//作为将小端数据变换为大端数据的宏
/*1*****************以下是发送arp请求包****************/
/*************************************************
函数名称:ARP请求包发送函数
调用入口:在主函数中调用的利用secureCRT控制台发送
函数说明:
**************************************************/
void arp_request()
{
memcpy(arpbuf.ethhdr.d_mac,host_mac_addr,6);//以太网的目的地址
memcpy(arpbuf.ethhdr.s_mac,mac_addr,6);//以太网的源地址
arpbuf.ethhdr.type = HON(0x0806);//帧类型,固定为0x0806(采用网络字节序大端格式
arpbuf.hwtype = HON(1);//硬件类型(采用网络字节序大端格式)
arpbuf.protocol = HON(0x0800);//协议类型,固定位0x0800(采用网络字节序大端格式)
arpbuf.hwlen = 6;//硬件地址长度
arpbuf.protolen = 4;//协议地址长度
arpbuf.opcode = HON(1);//opcode判断是请求包还是应答包
memcpy(arpbuf.smac,mac_addr,6);//源Mac地址
memcpy(arpbuf.sipaddr,ip_addr,4);//源IP地址
memcpy(arpbuf.dipaddr,host_ip_addr,4);//目的IP地址
packet_len = 14+28;
dm9000_tx(&arpbuf,packet_len);
}
/*************************************************
函数名称:ARP数据包的解析处理函数
调用入口:net_handle()_网络数据包处理分析函数
函数说明:判断是请求包还是应答包
**************************************************/
u8 arp_process(u8 *buf, u32 len)
{
u32 i;
ARP_HDR *arp_p = (ARP_HDR *)buf;//定义arp_p指针指向接收到的数据缓存区中
if (packet_len<28)//判断是否小于28字节,小于就不做处理
return 0;
switch (HON(arp_p->opcode))
{
case 2://若是ARP响应包,则打印在串口
/***************arp响应包***************/
memcpy(host_ip_addr,arp_p->sipaddr,4);//提取目的主机的IP地址,打印
printf("host ip is : ");
for(i=0;i<4;i++)
printf("%03d ",host_ip_addr[i]);
printf("\n\r");
memcpy(host_mac_addr,arp_p->smac,6);//提取目的PC机的MAC地址,打印
printf("host mac is : ");
for(i=0;i<6;i++)
printf("%02x ",host_mac_addr[i]);
printf("\n\r");
break;
case 1: //若是arp请求包,则发送ARP响应包
/***********发送arp响应包**************/
memcpy(arpbuf.ethhdr.d_mac,arp_p->smac,6);//以太网的目的地址
memcpy(arpbuf.ethhdr.s_mac,mac_addr,6);//以太网的源地址
arpbuf.ethhdr.type = HON(0x0806);//帧类型,固定为0x0806(采用网络字节序大端格式)
arpbuf.hwtype = HON(1);//硬件类型(采用网络字节序大端格式)
arpbuf.protocol = HON(0x0800);//协议类型,固定位0x0800(采用网络字节序大端格式)
arpbuf.hwlen = 6;//硬件地址长度
arpbuf.protolen = 4;//协议地址长度
arpbuf.opcode = HON(2);//opcode判断是请求包还是应答包
memcpy(arpbuf.smac,mac_addr,6);//源Mac地址
memcpy(arpbuf.sipaddr,ip_addr,4);//源IP地址
memcpy(arpbuf.dmac,arp_p->smac,6);//目的MAC地址
memcpy(arpbuf.dipaddr,arp_p->sipaddr,4);//目的IP地址
packet_len = 14+28;//总体包的长度
dm9000_tx(&arpbuf,packet_len);//调用dm9000发送函数,发送应答包
break;
}
}
/*************************************************
函数名称:UDP协议数据包处理函数
调用入口:在ip_process()接收到的IP类型的数据包处理函数
函数说明:UDP协议包下封装的是TFT协议包
**************************************************/
void udp_process(u8* buf, u32 len)
{
UDP_HDR *udphdr = (UDP_HDR *)buf;//定义udphdr 指针指向接收到的数据缓存区中
tftp_process(buf,len,HON(udphdr->sport)); //调用tftp_process()TFTP处理函数
}
/************************************************
函数名称:接收到的IP类型的数据包处理函数
调用接口:在net_handle网络数据包处理分析函数中
函数说明:IP协议包下封装的是UDP协议包
**************************************************/
void ip_process(u8 *buf, u32 len)
{
IP_HDR *p = (IP_HDR *)buf; //定义p指针指向接收到的数据缓存区中
switch(p->proto)//判断协议类型是否为UDP的协议包
{
case PROTO_UDP://如果是则调用udp_processUDP处理函数
udp_process(buf,len);
break;
default:
break;
}
}
/*********************************
函数名称:网络数据包处理分析函数
调用接口:调用者在DM9000的int_issue()函数处
********************************/
void net_handle(u8 *buf, u32 len)
{
ETH_HDR *p = (ETH_HDR *)buf; //定义p指针指向接收到的数据缓存区中
switch (HON(p->type))//判断接收到的数据包的类型
{
case PROTO_ARP://PROTO_ARP = 0x0806
arp_process(buf,len);//如果是ARP包则调用arp_process处理函数
break;
case PROTO_IP://PROTO_IP = 0x0800
ip_process(buf,len);//如果是IP包则调用ip_process处理函数
break;
default:
break;
}
}
3调用TFTP.C处理
#include "string.h"
#include "arp.h"
u8 sendbuf[1024];//发送缓存区
u8* tftp_down_addr = 0x31000000;//数据保存的起始地址
u16 serverport = 0;//源端口号
u16 curblock = 1;//数据的块号
#define HON(n) ((((u16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))//2个字节的数据更改为网络字节序,大端数据
/*************************************************
函数名称:计算校验码长度的函数
调用入口:tftp_send_request()
函数说明:无
**************************************************/
u16 checksum(u8 *ptr, int len)
{
u32 sum = 0;
u16 *p = (u16 *)ptr;
while (len > 1)
{
sum += *p++;
len -= 2;
}
}
if(len == 1)
sum += *(u8 *)p;
while(sum>>16)
sum = (sum&0xffff) + (sum>>16);
return (u16)((~sum)&0xffff);
}
/*************************************************
函数名称:发送tftp请求数据包的函数
调用入口:在主函数中调用的利用secureCRT控制台发送
函数说明:
**************************************************/
void tftp_send_request(const char *filename)
{
u8 *ptftp = &sendbuf[200];//TFTP的内存起始地址指向sendbuf缓存区
u32 tftp_len = 0;//TFTP请求报文的长度
UDP_HDR *udphdr;//定义UDP头的内存指向udphdr
u8 *iphdr;//定义IP头的内存指向iphdr
ptftp[0] = 0x00;
ptftp[1] = 0x01;//写入操作码,网络字节序大端数据
tftp_len += 2 ;//TFTP数据报文的长度变量
sprintf(&ptftp[tftp_len],"%s",filename);//利用sprintf函数写入请求的文件名
tftp_len += strlen(filename);//计算写入的文件名的长度
ptftp[tftp_len] = '\0';//添加文件名的结束符
tftp_len += 1;//长度加1
sprintf(&ptftp[tftp_len],"%s","octet");//利用sprintf函数写入传输数据的模式
tftp_len += strlen("octect");//计算写入的传输数据的模式的长度
ptftp[tftp_len] = '\0';//添加文件名的结束符
tftp_len += 1;//长度加1
udphdr = ptftp-sizeof(UDP_HDR);//利用sizeof函数计算UDP头的长度
iphdr = ptftp-sizeof(UDP_HDR)+ sizeof(ETH_HDR);//利用sizeof函数计算IP头的长度
/***************以下是UDP帧头信息****************/
udphdr->sport = HON(48915);//UDP头的16位源端口号
udphdr->dport = HON(69);//UDP头的16位目的端口号
udphdr->len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(IP_HDR));//UDP头的16位长度
udphdr->udpchksum = 0x00;//UDP头的16位校验码
/***************以下IP帧头信息*******************/
udphdr->iphdr.vhl = 0x45;//版本和报文长度
udphdr->iphdr.tos = 0x00;//服务级别
udphdr->iphdr.len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(ETH_HDR));//报文长度(采用网络字节序大端格式)
udphdr->iphdr.ipid = HON(0x00);//标识(采用网络字节序)
udphdr->iphdr.ipoffset = HON(0x4000);//标志(采用网络字节序大端格式)
udphdr->iphdr.ttl = 0xff;//报文的生存时间
udphdr->iphdr.proto = 17;//用户协议类型
memcpy(udphdr->iphdr.srcipaddr,ip_addr,4);//源iP地址
memcpy(udphdr->iphdr.destipaddr,host_ip_addr,4);//目的IP地址
udphdr->iphdr.ipchksum = 0;//首先将报文校验设置为0
udphdr->iphdr.ipchksum = checksum(iphdr,20);//利用checksum函数计算校验码的长度
memcpy(udphdr->iphdr.ethhdr.s_mac,mac_addr,6);//源MAC地址
memcpy(udphdr->iphdr.ethhdr.d_mac,host_mac_addr,6);//目的MAC地址
udphdr->iphdr.ethhdr.type = HON(PROTO_IP);//IP的协议类型(采用网络字节序,大端格式)
dm9000_tx((u32 *)udphdr,sizeof(UDP_HDR)+tftp_len);//利用dm9000_tx发送TFTP请求报文
}
/*************************************************
函数名称:接收tftp请求数据包确认的函数
调用入口:tftp_process()TFTP协议数据包处理函数
函数说明:处理完成后利用dm9000_tx()函数发送响应报文
**************************************************/
void tftp_send_ack(u16 blocknum)
{
u8 *ptftp = &sendbuf[200];//ptftp指针指向sendbuf缓存区中
u32 tftp_len = 0;//TFTP请求报文的长度
UDP_HDR *udphdr;//定义UDP头的内存指向udphdr
u8 *iphdr;//定义IP头的内存指向iphdr
ptftp[0] = 0x00;//写入操作码,网络字节序大端数据
ptftp[1] = 0x04;
tftp_len += 2 ;//TFTP数据报文的长度变量
ptftp[2] = (blocknum&0xff00)>>8;//提取客户端发送的数据报文中的块号
ptftp[3] = (blocknum&0xff);//因为采用的是网路字节序大端格式,则要变换为小端个数
tftp_len += 2 ;//TFTP数据报文的长度变量加2个季节
udphdr = ptftp-sizeof(UDP_HDR);//利用sizeof函数计算UDP头的长度
iphdr = ptftp-sizeof(UDP_HDR)+ sizeof(ETH_HDR);//利用sizeof函数计算IP头的长度
/****************以下是UDP帧头信息***************/
udphdr->sport = HON(48915);;//UDP头的16位源端口号(采用网络字节序大端格式)
udphdr->dport = HON(serverport);//UDP头的16位目的端口号(采用网络字节序大端格式)
udphdr->len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(IP_HDR));//UDP头的16位长度
udphdr->udpchksum = 0x00;//UDP头的16位校验码
/******************以下是IP帧头信息******************/
udphdr->iphdr.vhl = 0x45;//版本和报文长度
udphdr->iphdr.tos = 0x00;//服务级别
udphdr->iphdr.len = HON(tftp_len+sizeof(UDP_HDR)-sizeof(ETH_HDR));//报文长度(采用网络字节序大端格式)
udphdr->iphdr.ipid = HON(0x00);//标识(采用网络字节序)
udphdr->iphdr.ipoffset = HON(0x4000);//标志(采用网络字节序大端格式)
udphdr->iphdr.ttl = 0xff;//报文的生存时间
udphdr->iphdr.proto = 17;//用户协议类型
memcpy(udphdr->iphdr.srcipaddr,ip_addr,4);//源iP地址
memcpy(udphdr->iphdr.destipaddr,host_ip_addr,4);//目的IP地址
udphdr->iphdr.ipchksum = 0;//首先将报文校验设置为0
udphdr->iphdr.ipchksum = checksum(iphdr,20);//利用checksum函数计算校验码的长度
memcpy(udphdr->iphdr.ethhdr.s_mac,mac_addr,6);//源MAC地址
memcpy(udphdr->iphdr.ethhdr.d_mac,host_mac_addr,6);//目的MAC地址
udphdr->iphdr.ethhdr.type = HON(PROTO_IP);//IP的协议类型(采用网络字节序,大端格式)
dm9000_tx((u32 *)udphdr,sizeof(UDP_HDR)+tftp_len);//利用dm9000_tx发送TFTP请求报文
}
/***************************************************
函数名称:TFTP协议数据包处理函数
调用接口:在arp.C中的udp_process()UDP协议数据包处理函数
函数说明:len表示整个接收到的数据包长度,包括:
----------------------------------------------
| IP帧头 || UDP帧头 || TFTP帧头 || tftp数据 ||
----------------------------------------------
****************************************************/
void tftp_process(u8 *buf, u32 len, u16 port)
{
u32 i;
u32 tftp_len;//TFTP协议包长度
serverport = port;//源端口号
TFTP_PAK *ptftp = buf + sizeof(UDP_HDR);//定义ptftp 指针指向接收到的数据缓存区中
tftp_len = len - sizeof(UDP_HDR);//TFTP协议包长度
if(HON(ptftp->opcode) == 3)//当OPCODE=3时,表示该网络包是TFTP的数据报文
{
if (HON(ptftp->blocknum) == curblock)//按照块编号判断是否是最后一组数据报文
{
for (i = 0;i<(tftp_len-4);i++)//复制数据到指定的内存中去
{
*(tftp_down_addr) = *(ptftp->data+i);
}
tftp_send_ack(HON(ptftp->blocknum));//客户端发送接收数据的应答包
curblock++; //更新标志块的编号
if ((tftp_len-4)<512)
curblock = 1;//判断是否为最后一个数据包,若是则更新内存块的编号
tftp_down_addr = 0x31000000; //更新内存地址
}
}
}
4 部分MAIN函数
switch (num)
{
case 1:
tftp_send_request("start.o");
Break;
case 2:
arp_request();
break;
default:
printf("Error: wrong selection!\n\r");
break;
}
5 dm9000中的处理函数
/************************
接收数据函数
在外部中断处理函数中调用
***********************/
void int_issue()
{
packet_len = dm9000_rx(&buffer[0]); //计算接收到的数据包长度
net_handle(&buffer[0],packet_len);//调用此函数进行数据包的opcode类型分析
SRCPND = (1<<4);//清楚中断标志位
INTPND = (1<<4);
EINTPEND |= 1<<7;
}
TFTP网络协议分析---15的更多相关文章
- PYTHON黑帽编程1.5 使用WIRESHARK练习网络协议分析
Python黑帽编程1.5 使用Wireshark练习网络协议分析 1.5.0.1 本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks At ...
- linux 网络协议分析---3
本章节主要介绍linxu网络模型.以及常用的网络协议分析以太网协议.IP协议.TCP协议.UDP协议 一.网络模型 TCP/IP分层模型的四个协议层分别完成以下的功能: 第一层 网络接口层 网络接口层 ...
- wareshark网络协议分析之DHCP
声明:本文关于DHCP协议介绍部分摘自百度百科 一.DHCP协议介绍: DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用 ...
- [国嵌攻略][068][tftp网络协议实现]
IP协议结构 UDP协议结构 TFTP协议结构 TFTP端口 读写请求端口: 69 其他请求端口:1024~65535 主程序 /*********************************** ...
- 网络协议分析之wireshark---抓包使用
Wireshark基本介绍和学习TCP三次握手 之前写过一篇博客:用 Fiddler 来调试HTTP,HTTPS. 这篇文章介绍另一个好用的抓包工具wireshark, 用来获取网络数据封包,包括ht ...
- wareshark网络协议分析之ARP
一.ARP协议简介 简单的说ARP协议就是实现ip地址到物理地址的映射.当一台主机把以太网数据帧发送到位于同一局域网上的另一台主机时,是根据48bit的以太网地址(物理地址)来确定网络接口的. ARP ...
- linux网络协议
网络协议 本章节主要介绍linxu网络模型.以及常用的网络协议分析以太网协议.IP协议.TCP协议.UDP协议 一.网络模型 TCP/IP分层模型的四个协议层分别完成以下的功能: 第一层 网络接口层 ...
- UNIX网络编程——分析一帧基于UDP的TFTP协议帧
下图是UDP的段格式: 相比TCP段格式,UDP要简单得多,也没啥好说的,需要注意的是UDP数据长度指payload加上首部的长度. 下面分析一帧基于UDP的TFTP协议帧: 以太网首部 0000: ...
- Wireshark数据抓包分析——网络协议篇
Wireshark数据抓包分析--网络协议篇 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGF4dWViYQ==/ ...
随机推荐
- IT公司100题-11-求二叉树中节点的最大距离
问题描述: 写程序,求一棵二叉树中相距最远的两个节点之间的距离. 10/ \6 14/ \ / \4 8 12 16 分析: 二叉树中最远的两个节点,要么是根 ...
- HDU 5382 莫比乌斯反演
题目大意: 求S(n)的值 n<=1000000 这是官方题解给出的推导过程,orz,按这上面说的来写,就不难了 这里需要思考的就是G(n)这个如何利用积性函数的性质线性筛出来 作为一个质数,那 ...
- BPM的四大主要类型
随着网络的发展,移动BPM.社交BPM.云端BPM将顺应市场需求,成为BPM发展的新趋势,最终成为企业即时管控有效工具.BPM将不断促进制造业信息化的转型与发展.所以很少人会否认业务流程管理(BPM) ...
- MicroPython开发板TPYBoard关于USB-HID的应用
USB-HID是Human Interface Device的缩写,属于人机交互操作的设备,如USB鼠标,USB键盘,USB游戏操纵杆,USB触摸板,USB轨迹球.电话拨号设备.VCR遥控等等设备. ...
- Day1 summary
对比了几篇在hadoop环境中实现关联规则.频繁项集的论文,文章结构都涉及mapreduce模型.传统与改进apriori算法比较.实验结果分析(数据规模-用时or加速比,节点-用时or加速比).有一 ...
- 算法(第4版)-1.1.7 API
总结:本小姐讲述了API的定义.作用以及一些Java库的举例. 重点: 1.API的目的是将调用和实现分离:除了API中给出的信息,调用者不需要知道实现的其他细节,而实现也不应考虑特殊的应用场景.
- What is the difference Apache (Http Server) and Tomcat (Servlet Container)
The Apache Project The Apache Project is a collaborative software development effort. Its goal is to ...
- 封装数据库mysql, mysqli
<?php header("content-type:text/html;charset=utf-8"); class db{ //私有的静态属性 private ...
- PHP_string
\n 换行 \r 回车 \t 制表符 \$ 美元符 \0 八进制数 \x 十六进制数 \\ 反斜杠字符
- TableView--通讯录--开篇
一,需求图: