【问题标题】:perl bitwise AND and bitwise shiftingperl 按位与和按位移位
【发布时间】:2014-10-15 22:33:55
【问题描述】:

我正在阅读模块 Net::Pcap::Easy 的一些示例代码 sn-p,我遇到了这段代码

my $l3protlen = ord substr $raw_bytes, 14, 1;
my $l3prot = $l3protlen & 0xf0 >> 2;    # the protocol part
return unless $l3prot == 4;    # return unless IPv4
my $l4prot = ord substr $packet, 23, 1;
return unless $l4prot == '7';

在对原始数据包 $raw_bytes 进行完整的十六进制转储后,我可以看到这是一个以太网帧,而不是 TCP/UDP 数据包。有人可以解释一下上面的代码是做什么的吗?

【问题讨论】:

    标签: perl bit-manipulation libpcap


    【解决方案1】:

    为了解析帧,我查了this page

    现在到 Perl...

    my $l3protlen =  ord substr $raw_bytes, 14, 1;
    

    $raw_bytes 中提取第 15 个字节(字符),并转换为其序数值(例如,假设字符集为 ASCII,字符“A”将转换为整数 65 (0x41))。这就是 Perl 处理二进制数据的方式,就像它是一个字符串一样(例如,将它传递给substr),然后让您将二进制值取回并将它们作为数字处理。 (但请记住TMTOWTDI。)

    在 IPv4 帧中,前 14 个字节是 MAC 标头(目标和源 MAC 地址各 6 个字节,随后是 2 个字节的 Ethertype,可能是 0x8000 - 你可以检查一下)。在这之后,第 15 个字节是以太网数据负载的开始:第一个字节包含版本(高 4 字节)和以 DWORD 为单位的标头长度(低 4 字节)。

    现在在我看来,此示例代码的下一行中存在错误,但它可能正常工作是侥幸!

    my $l3prot    = $l3protlen & 0xf0 >> 2; # the protocol part
    

    在 Perl 中,>> 的优先级高于 &,因此这将等价于

    my $l3prot    = $l3protlen & (0xf0 >> 2);
    

    或者如果你喜欢

    my $l3prot    = $l3protlen & 0x3c;
    

    所以这会从$l3prot 值中提取位 2 - 5:掩码值 0x3c 是二进制的 0011 1100。例如,值 0x86(二进制 1000 0110)将变为 0x04(二进制 0000 0100)。 事实上,“正常”的 IPv4 值是 0x45,即协议类型 4,标头长度 5 个双字。用 0x3c 屏蔽它,你会得到...... 4!但只是侥幸:您测试了长度的前 2 位,而不是协议类型!

    这一行应该是

    my $l3prot = ($l3protlen & 0xf0) >> 4;
    

    (注意括号表示优先级和 4 位的移位,而不是 2 位)。 (我在CPAN documentation 中发现了同样的错误,所以我猜它可能传播得相当广泛。)

    return unless $l3prot == 4; # return unless IPv4
    

    对于 IPv4,我们希望该值为 4 - 如果不是,请立即跳出函数。 (所以上面的错误代码给出的结果是让它被解释为一个 IPv4 数据包,但只能靠运气。)

    my $l4prot = ord substr $packet, 23, 1;
    

    现在提取第 24 个字节并以相同的方式转换为序数值。这是来自 IP 标头的协议字节:

    return unless $l4prot == '7';
    

    我们预计这是 7 - 如果它没有立即跳出函数。 (根据IANA,7 是“基于核心的树”......但我想你知道你对哪些协议感兴趣!)

    【讨论】:

    • 解释得很好。是的,我专门寻找 udp,所以 7。
    • @nohup - 谢谢!但是 UDP 是 17,而不是 7...您是否也尝试过我建议的对“& 0xf0”行的更正?
    • 优秀且解释清楚。发现这些错误做得很好
    • 是的。我参考了您提供的链接,可以看到17 UDP User Datagram [RFC768][Jon_Postel]。是的,我想了解在从 cpan 文档中盲目复制之前我在做什么,并且正在使用 my $l3prot = ($l3protlen & 0xf0) >> 4;。非常感谢您帮助我理解这一点并发现错误。
    • @nohup - 谢谢,很高兴能够提供帮助!看似简单的 Perl 问题,结果却非常有趣(比我应该做的工作更有趣!)。
    猜你喜欢
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    相关资源
    最近更新 更多