TCP协议学习记录 (三) Ping程序 RR选项 记录路由hop
一开始想直接在上个程序改,自己构造IP包头,但后来发现不行,微软不让干了,所以后来选用libcap库来收发包
代码写的很乱..
#pragma pack(4) #define ECHO_REQUEST 8
#define DATASIZE 65500
#define PACKETSIZE 65535
#define IPCOUNT 9
#define MACSIZE 6
#define OPTION_RR 7 struct ethhdr
{
char mac_dst[MACSIZE];
char mac_src[MACSIZE]; unsigned short eth_protocol;
char eth_data[DATASIZE];
}; struct iphdr
{
unsigned char ip_hdr_len : ; //包头长度
unsigned char ip_version : ; //版本
unsigned char ip_tos; unsigned short ip_length; //总长度
unsigned short ip_identify;//标识
unsigned short ip_offset;//片偏移
unsigned char ip_ttl;
unsigned char ip_protocol;
unsigned short ip_cksum; struct in_addr ip_src; //源地址
struct in_addr ip_dst; //目的地址 unsigned char ip_code;
unsigned char ip_len;
unsigned char ip_ptr; struct in_addr ip_router[IPCOUNT]; char ip_data[DATASIZE];
}; struct icmphdr
{
unsigned char icmp_type; //8位类型
unsigned char icmp_code; //8位代码
unsigned short icmp_cksum; //16位的校验和 unsigned short icmp_identify;
unsigned short icmp_seq; LONGLONG icmp_timestamp;
char icmp_data[DATASIZE];
}; bool ping_rr(char * target,int payload,int count)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(, ), &wsaData); if(payload > DATASIZE)
{
printf("发送的字节数有错误,有效范围从 0 到 %d",DATASIZE);
return false;
} payload = payload - sizeof(LONGLONG); struct hostent* phostent = gethostbyname(target);
if (!phostent)
{
printf("解析IP失败!\n");
return false;
} struct in_addr addrSrv = {};
addrSrv.S_un.S_addr = *(u_long *)phostent->h_addr_list[]; printf("正在 Ping %s [%s] 具有 %d 字节的数据: \n",target,inet_ntoa(addrSrv),payload + sizeof(LONGLONG)); icmphdr ihdr = {};
iphdr ip_hdr = {};
ethhdr eth_hdr = {}; unsigned char mac_src[] = "\x68\xf7\x28\x7f\xc2\x71"; //本机MAC地址
unsigned char mac_dst[] = "\x84\xd9\x31\xb9\x21\x98"; //目的MAC地址 memcpy((void *)eth_hdr.mac_src,(void *)mac_src,sizeof(mac_src) -);
memcpy((void *)eth_hdr.mac_dst,(void *)mac_dst,sizeof(mac_dst) -); eth_hdr.eth_protocol = htons(); //0x0800 //链路层IP数据报 ip_hdr.ip_hdr_len = 0xf; //包头设置为最大长度
ip_hdr.ip_version = ;
ip_hdr.ip_identify = (unsigned short)GetCurrentProcessId();
ip_hdr.ip_offset = ;
ip_hdr.ip_ttl = 0x40;//默认设置为64
ip_hdr.ip_protocol = IPPROTO_ICMP;
ip_hdr.ip_src.s_addr = inet_addr("172.30.1.145"); //本机IP
ip_hdr.ip_dst.s_addr = *(u_long *)phostent->h_addr_list[];
ip_hdr.ip_code = OPTION_RR; //RR选项为7
ip_hdr.ip_len = 0x27; //39字节 最多能存9个IP地址
ip_hdr.ip_ptr = ;
ip_hdr.ip_cksum = ; memset((void *)ip_hdr.ip_router,,sizeof(struct in_addr) * IPCOUNT); memset((void *)ihdr.icmp_data,,DATASIZE);
memset((void *)ip_hdr.ip_data,,DATASIZE); packet_pad(ihdr.icmp_data,payload); //填充数据 ihdr.icmp_type = ECHO_REQUEST;
ihdr.icmp_identify = (unsigned short)GetCurrentProcessId(); int hdr_len = payload + sizeof(icmphdr) - DATASIZE;
int datalen = hdr_len + (ip_hdr.ip_hdr_len << );
int sendlen = datalen + sizeof(ethhdr) - DATASIZE;
ip_hdr.ip_length = htons(datalen); char recv[PACKETSIZE] = {}; unsigned long interval = ;
unsigned long avgdelay = ;
unsigned long maxdelay = ;
unsigned long mindelay = ~; unsigned int sendcnt = count;
unsigned int losscnt = ; char strErrorbuf[PCAP_ERRBUF_SIZE] = {}; std::string strNickName = "\\Device\\NPF_{D8AECAAE-F28C-4161-BA6B-BCA1B807F2E5}"; //本机网卡 pcap_t* pcap_handle = NULL;
if ((pcap_handle = pcap_open_live(strNickName.c_str(),,,,strErrorbuf))==NULL)
{
return false;
} if( pcap_datalink(pcap_handle) != DLT_EN10MB )
{
return false;
} unsigned int netip,netmask;
if (pcap_lookupnet(strNickName.c_str(),&netip,&netmask,strErrorbuf) < )
{
return false;
} std::string strFilter = "icmp"; //协议过滤 只抓icmp的包
struct bpf_program nFcode;
if ( pcap_compile(pcap_handle, &nFcode,strFilter.c_str(), , netmask) < )
{
return false;
} if ( pcap_setfilter(pcap_handle, &nFcode) < )
{
return false;
} int next = ; struct pcap_pkthdr * header = NULL;
const unsigned char* pkt_data = NULL; for(int seq = ; seq < count; ++seq)
{
memset((void *)ip_hdr.ip_router,,sizeof(struct in_addr) * IPCOUNT); ihdr.icmp_seq = seq;
ihdr.icmp_cksum = ;
ihdr.icmp_timestamp = GetSysTickCount64(); //发送时间
ihdr.icmp_cksum = checksum(hdr_len,(unsigned short *)&ihdr); memcpy((void *)ip_hdr.ip_data,(void *)&ihdr,hdr_len); ip_hdr.ip_cksum = ;
ip_hdr.ip_ptr = ;
ip_hdr.ip_cksum = checksum(datalen,(unsigned short *)&ip_hdr); memcpy((void *)eth_hdr.eth_data,(void *)&ip_hdr,datalen); if(pcap_sendpacket(pcap_handle,(unsigned char *)ð_hdr,sendlen) != ) //发送数据包
{
--sendcnt;
continue;
} while(next = pcap_next_ex(pcap_handle, &header, &pkt_data))
{
iphdr* piphdr = (iphdr *) (pkt_data + sizeof(ethhdr) - DATASIZE); if(checksum(piphdr->ip_hdr_len << ,(unsigned short *)piphdr) != )
{
printf("invalid ip packet!\n");
continue;
} icmphdr* pichdr = (icmphdr *)(pkt_data + sendlen - hdr_len);
if(checksum(hdr_len,(unsigned short *)pichdr) != )
{
printf("invalid icmp packet!\n");
continue;
} if(piphdr->ip_ptr == )
{
continue;
} memcpy((void *)piphdr->ip_router,(void *)((char *)piphdr->ip_router -),sizeof(struct in_addr) * IPCOUNT);//内存对齐问题 interval = GetSysTickCount64() - pichdr->icmp_timestamp;
avgdelay+= interval; maxdelay = interval > maxdelay ? interval : maxdelay;
mindelay = interval > mindelay ? mindelay : interval; int record = (piphdr->ip_ptr-) >> ; printf("来自 %s 的回复: 字节=%d 时间=%dms TTL=%u\n",inet_ntoa(addrSrv),payload + sizeof(LONGLONG),interval,piphdr->ip_ttl); printf(" 路由: %s -->\n",inet_ntoa(piphdr->ip_router[]));
for(int i = ; i < record;i++)
{
printf(" %s -->\n",inet_ntoa(piphdr->ip_router[i]));
} break;
} if(next == -)
{
losscnt++;
} } printf("\n");
printf("%s 的 Ping 统计信息: \n",inet_ntoa(addrSrv));
printf(" 数据包: 已发送 = %d, 已接收 = %d, 丢失 = %d (%.2f%% 丢失),\n",sendcnt,sendcnt-losscnt,losscnt,(losscnt * ) / (double)sendcnt);
printf("往返行程的估计时间(以毫秒为单位):\n");
printf(" 最短 = %dms, 最长 = %dms, 平均 = %dms\n",mindelay,maxdelay,avgdelay / sendcnt);
printf("\n"); return true;
}
TCP协议学习记录 (三) Ping程序 RR选项 记录路由hop的更多相关文章
- TCP/IP协议学习之实例ping命令学习笔记
TCP/IP协议学习之实例ping命令学习笔记(一) 一. 目的为了让网络协议学习更有效果,在真实网络上进行ping命令前相关知识的学习,暂时不管DNS,在内网中,进行2台主机间的ping命令的整个详 ...
- [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]
[网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...
- TCP协议中的三次握手和四次挥手(图解)【转】
建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. [更新于2017.01.04 ]该部分内容配图有误,请大家见谅,正确的配图如下,错误配图也不删 ...
- TCP协议学习记录 (二) Ping程序
简单的实现了一个ping程序,没有做icmp差错报文的检查. 支持自定义字节数,支持发包个数 #pragma pack(4) #define ECHO_REQUEST 8 #define DATASI ...
- TCP协议学习笔记(一)首部以及TCP的三次握手连接四次挥手断开
TCP协议是一种面向连接的.可靠的流协议. 流即不间断的数据结构.这样能够保证接收到数据顺序与发送相同.但是犹如数据间没有间隔,因此在TCP通信中,发送端应用可以在自己所要发送的消息中设置一个标示长度 ...
- TCP协议学习总结(上)
在计算机领域,数据的本质无非0和1,创造0和1的固然伟大,但真正百花齐放的还是基于0和1之上的各种层次之间的组合(数据结构)所带给我们人类各种各样的可能性.例如TCP协议,我们的生活无不无时无刻的站在 ...
- 计算机网络:这是一份全面 & 详细 的TCP协议学习指南
原文链接:blog.csdn.net 用这个媒体播放器组件,实时互动时也可共同观看本地视频juejin.im 前言 计算机网络基础 该是程序猿需掌握的知识,但往往会被忽略 今天,我将详细讲解计算机网络 ...
- TCP协议学习总结(中)
很多人都说TCP协议是一个十分复杂的协议,在学习当中,我对协议每一个问题都分解学习后,每一个分解我都能体会和理解它的要点,并不难理解.但我把这些拆分的细节合并后,确认感觉这样一个协议相对“臃肿”但又好 ...
- TCP协议学习笔记
TCP协议数据格式 TCP协议在互联网ISO协议的传输层. 在互联网传输过程中,互联网包在数据链路层,是传输数据的最基础的包.一个互联网的包包含IP包,即互联网包 = 互联网信息包头(至少20字节)+ ...
随机推荐
- oracle 实现ID自增
CREATE TABLE testTable1 ( ID INT NOT NULL, NAME ) NOT NULL, PRIMARY KEY(ID) ) TABLESPACE MYDB; --创建自 ...
- leetcode72. Edit Distance(编辑距离)
以下为个人翻译方便理解 编辑距离问题是一个经典的动态规划问题.首先定义dp[i][j表示word1[0..i-1]到word2[0..j-1]的最小操作数(即编辑距离). 状态转换方程有两种情况:边界 ...
- java使用jsch连接linux
由于项目需要使用java来linux进行管理,近一番查找,发现第三方jar包 jsch 可以轻松实现对linux的管理,(相关文档及例子请访问官网www.jcraft.com),故引进. 在网上搜索了 ...
- git和nginx安装
原始地址: https://www.zybuluo.com/freeethy/note/192109 git安装 设置git的username和email (注册gitlab的账号密码) $$ git ...
- Ninject之旅之六:Ninject约定
摘要 在小的应用系统中一个一个注册一些服务类型不怎么困难.但是,如果是一个实际的有上百个服务的应用程序呢?约定配置允许我们使用约定绑定一组服务,而不用一个一个分别绑定. 要使用约定配置,需要添加Nin ...
- Leetcode4:Median of Two Sorted Arrays@Python
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...
- 笔试常考的Linux命令大全
1. wc -l 统计一个文件的行数.l-line.-c是字节数,-m是字符数,mc不能同时使用.-L打印最长行的长度. 2. 查看系统进程的命令:ps,查看CPU占用命令:top.df:查看磁盘使用 ...
- SSM项目配置随笔
一.自动扫描 使用Annotation自动注册Bean:在主容器中不扫描@Controller注解,在SpringMvc中只扫描@Controller注解. 1.spring配置文件(扫描注解) &l ...
- Centos7上安装dnf-plugins-core
为了在Centos上使用dnf copr命令,需要安装dnf-plugins-core,找了很长时间,包括试了源码编译安装都不行,最后找到了方法,执行下面的命令就可以了. 需要root权限 wget ...
- mysql5.7忘记密码
注意:mysql5.7 user表密码字段由password改为authentication_string 1.service mysql stop 2.mysqld_safe --skip-gran ...