- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想使用 libpcap 来捕获 IP 数据包,并且我想解析 IP header 和 tcp header 。`
<netinet/ip.h>
中有IP头和TCP头结构和 <netinet/tcp.h>
IP header相对容易解析,但是对于TCP header,因为有tcp选项,常用选项有MSS、SACK(选择性确认)、时间戳、窗口缩放和NOP。
我想要一个函数 parse_pkt():
struct tcphdr tcp_hdr;
struct ip ip_hdr;
parse_pkt(u_char *pcap_packet, struct ip* p_ip, struct tcp* p_tcp);
所以调用该函数后,如果我想知道源ip地址、序列号和MSS,
scr_ip = ip_hdr.src_ip
seq = tcp_hdr.seq
mss = tcp_hdr.mss
是否有类似的源代码/片段可以满足我的要求?谢谢!
最佳答案
(下面的第一个示例)这是我正在制作的东西(在 C++11 中)。这是针对 UDP 数据包的,但您可以通过添加相关的结构和 Net::load()
模板来使其适用于 TCP 数据包,如下所示。
(下面的第二个例子)你没有在问题中指定目标语言,但如果你正在寻找 C,那么你可以在结构上使用 #pragma pack
然后转换pointer+offset 作为指向结构的指针,然后在适当的字段上调用 ntohs/ntohl。这样做可能是最快的解决方案,但它依赖于 #pragma pack
,这不是标准的。
net.h:
namespace Net {
using addr_t = uint32_t;
using port_t = uint16_t;
struct ether_header_t {
uint8_t dst_addr[6];
uint8_t src_addr[6];
uint16_t llc_len;
};
struct ip_header_t {
uint8_t ver_ihl; // 4 bits version and 4 bits internet header length
uint8_t tos;
uint16_t total_length;
uint16_t id;
uint16_t flags_fo; // 3 bits flags and 13 bits fragment-offset
uint8_t ttl;
uint8_t protocol;
uint16_t checksum;
addr_t src_addr;
addr_t dst_addr;
uint8_t ihl() const;
size_t size() const;
};
class udp_header_t {
public:
port_t src_port;
port_t dst_port;
uint16_t length;
uint16_t checksum;
};
template< typename T >
T load( std::istream& stream, bool ntoh = true );
template<>
ip_header_t load( std::istream& stream, bool ntoh );
template<>
udp_header_t load( std::istream& stream, bool ntoh );
std::string to_string( const addr_t& addr );
}
net.cpp:
namespace Net {
uint8_t ip_header_t::ihl() const {
return (ver_ihl & 0x0F);
}
size_t ip_header_t::size() const {
return ihl() * sizeof(uint32_t);
}
template<>
ip_header_t load( std::istream& stream, bool ntoh ) {
ip_header_t header;
stream.read((char*)&header.ver_ihl, sizeof(header.ver_ihl));
stream.read((char*)&header.tos, sizeof(header.tos));
stream.read((char*)&header.total_length, sizeof(header.total_length));
stream.read((char*)&header.id, sizeof(header.id));
stream.read((char*)&header.flags_fo, sizeof(header.flags_fo));
stream.read((char*)&header.ttl, sizeof(header.ttl));
stream.read((char*)&header.protocol, sizeof(header.protocol));
stream.read((char*)&header.checksum, sizeof(header.checksum));
stream.read((char*)&header.src_addr, sizeof(header.src_addr));
stream.read((char*)&header.dst_addr, sizeof(header.dst_addr));
if( ntoh ) {
header.total_length = ntohs(header.total_length);
header.id = ntohs(header.id);
header.flags_fo = ntohs(header.flags_fo);
header.checksum = ntohs(header.checksum);
header.src_addr = ntohl(header.src_addr);
header.dst_addr = ntohl(header.dst_addr);
}
return header;
}
template<>
udp_header_t load( std::istream& stream, bool ntoh ) {
udp_header_t header;
stream.read((char*)&header.src_port, sizeof(header.src_port));
stream.read((char*)&header.dst_port, sizeof(header.dst_port));
stream.read((char*)&header.length, sizeof(header.length));
stream.read((char*)&header.checksum, sizeof(header.checksum));
if( ntoh ) {
header.src_port = ntohs(header.src_port);
header.dst_port = ntohs(header.dst_port);
header.length = ntohs(header.length);
header.checksum = ntohs(header.checksum);
}
return header;
}
}
数据包捕获处理程序中的客户端代码:
using std::chrono::seconds;
using std::chrono::microseconds;
using clock = std::chrono::system_clock;
using Net::ether_header_t;
using Net::ip_header_t;
using Net::udp_header_t;
auto packet_time = clock::time_point(seconds(header->ts.tv_sec) + microseconds(header->ts.tv_usec));
std::istringstream stream(std::string((char*)packet, header->caplen));
stream.seekg(sizeof(ether_header_t), std::ios_base::beg);
auto ip_header = Net::load<ip_header_t>(stream);
if( ip_header.size() > 20 ) {
stream.seekg(ip_header.size() + sizeof(ether_header_t), std::ios_base::beg);
}
auto udp_header = Net::load<udp_header_t>(stream);
(对于任何错误,我深表歉意。我凭内存输入,并没有尝试编译或运行——但我想你会理解基本思想):
net.h:
typedef uint32_t addr_t;
typedef uint16_t port_t;
#pragma pack(push, 1)
typedef struct {
uint8_t dst_addr[6];
uint8_t src_addr[6];
uint16_t llc_len;
} ether_header_t;
typedef struct {
uint8_t ver_ihl; // 4 bits version and 4 bits internet header length
uint8_t tos;
uint16_t total_length;
uint16_t id;
uint16_t flags_fo; // 3 bits flags and 13 bits fragment-offset
uint8_t ttl;
uint8_t protocol;
uint16_t checksum;
addr_t src_addr;
addr_t dst_addr;
} ip_header_t;
typedef struct {
port_t src_port;
port_t dst_port;
uint16_t length;
uint16_t checksum;
} udp_header_t;
#pragma pack(pop)
数据包处理程序中的客户端代码:
ip_header_t ip_header = (ip_header_t)*(packet + sizeof(ether_header_t));
ip_header.total_length = ntohs(ip_header.total_length);
ip_header.id = ntohs(ip_header.id);
ip_header.flags_fo = ntohs(ip_header.flags_fo);
ip_header.checksum = ntohs(ip_header.checksum);
ip_header.src_addr = ntohl(ip_header.src_addr);
ip_header.dst_addr = ntohl(ip_header.dst_addr);
int ip_size = 4 * (ip_header.ver_ihl & 0x0F);
udp_header_t udp_header = (udp_header_t)*(packet + ip_size + sizeof(ether_header_t));
udp_header.src_port = ntohs(udp_header.src_port);
udp_header.dst_port = ntohs(udp_header.dst_port);
udp_header.length = ntohs(udp_header.length);
udp_header.checksum = ntohs(udp_header.checksum);
根据netinet/tcp.h
,TCP头部大致为:
typedef struct {
uint16_t src_port;
uint16_t dst_port;
uint32_t seq;
uint32_t ack;
uint8_t data_offset; // 4 bits
uint8_t flags;
uint16_t window_size;
uint16_t checksum;
uint16_t urgent_p;
} tcp_header_t;
使用您喜欢的任何方法将此结构加载到内存中,并且不要忘记如上所述修复多字节整数类型的字节顺序 (ntohs/ntohl)。
后面是 TCP 选项,不能像这样加载到结构中。请参阅此处有关 TCP 选项的部分 link .对于 MSS,您需要解析每个选项,直到找到 kind == 2 的选项。基于上面的 C 示例构建:
typedef struct {
uint8_t kind;
uint8_t size;
} tcp_option_t;
uint16_t mss;
uint8_t* opt = (uint8_t*)(packet + ip_size + sizeof(ether_header_t) + sizeof(tcp_header_t))
while( *opt != 0 ) {
tcp_option_t* _opt = (tcp_option_t*)opt;
if( _opt->kind == 1 /* NOP */ ) {
++opt; // NOP is one byte;
continue;
}
if( _opt->kind == 2 /* MSS */ ) {
mss = ntohs((uint16_t)*(opt + sizeof(opt)));
}
opt += _opt->size;
}
关于networking - 解析 libpcap 捕获的数据包的 IP 和 TCP header (尤其是常见的 tcp header 选项),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16519846/
新建表: create table [表名] ( [自动编号字段] int IDENTITY (1,1)&nbs
我的文件中有正在本地化的字符串。其中许多是常见的,并且已经在整个 iOS 中使用。例如。 “保存”、“加载”、“返回”、“收藏夹”、“拍照”。为了与其他应用程序和内置应用程序提供一致的用户体验,是否有
我已经学习了 Qt 的基础知识,现在对这个漂亮的库的深度感兴趣。请帮助我理解: 所有类都是从QObject派生的吗? 为什么可以在QWidget(和派生类)上绘画? return app.exec()
我在 webpack 中设置了一个自调用函数,并使用常见的 JS 来需要一些包: (function() { var $ = require("jquery"); //...my functi
我正在尝试制作一个大量使用词性标记的应用程序。但是 nltk 的 pos 标记功能对我来说似乎不符合标准 - 例如: import nltk text = "Obama delivers his fi
有没有办法处理发送到 MySQL 的常见查询以防止不必要的带宽使用? 最佳答案 选项是: 使用MySQL缓存查询 好:全自动 差:仍然需要访问数据库服务器;有一次缓存让我在一个项目中失望,花了很长时间
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 4 年前。 Improve this qu
关闭。这个问题需要debugging details .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 6年前关闭。 Improve this questio
我正在尝试调用返回 csv 文件的网络服务。因此,我调用的每个 URL 都有一个后缀,它是一个字符串,表示要生成哪个 csv。然后我想将此 csv 保存到文件中。有很多要生成,所以我从多个线程调用此类
流行手机型号支持的典型触摸点数量是多少?我在基础研究中看到低至 2 和高至 5,但我希望能够将其映射到实际手机和更好的限制! 最佳答案 两部手机的触控点数据: Galaxy S 5 LG
出于好奇 - 我知道有 LAMP - Linux、Apache、MySQL 和 PHP。但是还有哪些其他 Web 堆栈替代方案的缩写呢?像 LAMR - Linux、Apache、MySQL Ruby
我写了一个java代码(使用apache common vfs2)来上传文件到SFTP服务器。最近,我在我的服务器上引入了 PGP 安全性。现在,java 代码无法连接到该服务器。与 FileZill
由于 GLU 被认为对于现代 OpenGL (3.1+) 来说已经过时,那么使用 C/C++ 在 OpenGL 中绘制基本形状(例如椭圆或弧线/饼图)的方法是什么?令人难以置信的是,在 OpenGL
我想知道是否有最流行的 iOS 应用程序的自定义 URL 方案列表,例如 Keynote、Numbers、Pages、Evernote 等。我还想知道这些应用程序使用什么参数网址。 我需要这个的原因是
我正在使用 NDK r10d 移植 C++ myToll Linux 应用程序以在 Android 上运行。 (请注意,这不是带有 apk 的 Android 应用程序,而是从 shell 运行的实用
假设您想要使用 UML 2 部署图为在该领域没有太多知识的人可视化一个常见的 PHP 服务器应用程序。这样一个通用的应用程序可能有三个设备节点(数据库服务器、Web 服务器和客户端)和四个执行环境节点
我正在尝试运行以下代码,以找到两个人之间的共同 friend 。输入如下 A : B C D B : A C D E C : A B D E D : A B C E E : B C D 我无法在输出文
我在 Gitolite 的 manual 中找到的唯一东西在钩子(Hook)上,是: If you want to add your own hook, it's easy as long as it
具体来说,我有一个问题,在 AWS 环境中组织 AZ 故障转移的推荐方法是什么。此外,最好了解典型的 AWS 故障以组织应用程序 HA(高可用性)。 因此,应用程序架构(AWS 服务使用)如下: 它或
我正在尝试编写一个通用的 SecurePagingAndSorting 存储库,它将检查 CRUD 操作的安全性,以节省在所有 JPA 存储库中重复相同的 PreAuthorize(使用不同的权限)。
我是一名优秀的程序员,十分优秀!