type
status
date
slug
summary
tags
category
icon
password
URL
WIFI MAC地址必须是单播地址
在我们做项目的时候,MTK平台我们可以在CFG_WIFI_Default.h中修改wifi的mac地址,高通平台可以通过写nv#4678来修改(详细可见[wifi] 高通平台 wlan mac 地址分析以及更改方法 - DoReMi )
但是如果mac地址设置不正确,会出现问题的!
driver中实现了专门的set_mac_addr函数,察看该函数,发现原来会检验该mac地址的有效性。

这边会检测是否为多播地址以及是不是全0地址

组播地址就是第一个字节最低位为1,问题就是在这里。
发现第一个字节最低位为1时该函数就会返回0,driver中的set_mac_addr就会返回EADDRNOTAVAIL错误码。
严格来说mac地址对于每块网卡是固定的,每块网卡被生产出来后,都会有一个全球唯一的编号来标识自己,不会重复,
这个编号就是MAC地址,也就是网卡的物理地址。MAC地址是由48位的二进制数组成,即6个字节。在通信中是用16进制表示的。
前24位是由生产厂家向IEEE标准组织申请的厂家代码,是固定的,但是第一个字节的最低位一定是0,因为网卡的物理地址,一定是单播地址,
在IPv4的环境中,区分单播和组播地址就是校检最低位的二进制数字,0代表单播地址,1代表组播地址。
也就是说第二个数字一定是0、2、4、6、8、A、C、E其中的一个。
所以mac地址虽然可以修改,但是不要乱改,要按照厂商规定来修改,以免重复。
我们是在写 wifi mac地址时候,比较随意, 写了比如:91:00:01:03:32:32 地址, 91 就造成了 mac地址变成了 组播地址,但是ifconfig 没有报错
而是在 brctl addif br0 wlan0的时候出错了,提升 无效网络设备
这个经验很重要
附:
单播MAC地址:指第一个字du节的最低位是0的MAC地址zhi。
如:xxxxxxx0-xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx
组播MAC地址:指第一个字节zhuan的最低位是1的MAC地址。
如:xxxxxxx1-xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx
广播MAC地址:每个比特都是1的MAC地址。广播是组播的一个特例。
如:11111111-11111111-11111111-11111111-11111111-11111111
mac 地址格式详解
以太网编址
在数据链路层,数据帧通常依赖于 MAC 地址来进行数据交换,它如同公网 IP 地址一样要求具有全球唯一性,这样才可以识别每一台主机。那么 MAC 地址如何做到这点?它的格式又是什么?
MAC 地址,英文全称 Medium Access Control,直译为介质访问控制,它通常被固化在每个以太网网卡(NIC,Network Interface Card)。MAC(硬件)地址长 48 位(6 字节),采用十六进制格式,下图说明了 48 位的 MAC 地址及其组成部分。

示例: 00-01-6C-06-A6-29 或 00:01:6C:06:A6:29
组织唯一标识符(OUI)由 IEEE(电气和电子工程师协会)分配给厂商,它包含 24 位。厂商再用剩下的 24 位(EUI,扩展唯一标识符)为其生产的每个网卡分配一个全球唯一的全局管理地址,一般来说大厂商都会购买多个 OUI。
I/G(Individual/Group)位,如果 I/G=0,则是某台设备的 MAC 地址,即单播地址;如果 I/G=1,则是多播地址(组播 + 广播 = 多播)。
G/L(Global/Local,也称为 U/L 位,其中 U 表示 Universal)位,如果 G/L=0,则是全局管理地址,由 IEEE 分配;如果 G/L=1,则是本地管理地址,是网络管理员为了加强自己对网络管理而指定的地址。
对于 I/G 和 G/L 位的位置,目前有两种说法,或者说两种格式。
对于数据传输来说,数据是按每个字节中一位一位地传输的,一个字节传输完了才到下一个字节。
IEEE 802.3 :以太网介质访问控制协议 (CSMA/CD)及物理层技术规范。IEEE 802.4 :令牌总线网(Token-Bus)的介质访问控制协议及物理层技术规范。IEEE 802.5 :令牌环网(Token-Ring) 的介质访问控制协议及物理层技术规范。IEEE 802.6 :城域网介质访问控制协议 DQDB (Distributed Queue Dual Bus 分布式队列双总线)及物理层技术规范。

第一种,每个字节的高位在前,低位在后,I/G 位和 G/L 分别在字节中的最低位和次低位,最高位先发送,到了对端还是最高位
第二种,每个字节的低位在前,高位在后,I/G 位和 G/L 分别在字节中的最低位和次低位,最低位先发送,到了对端还是最低位
两种看似不一样,但是结果还是一样的,如果还是弄不懂可以再草稿纸上画一画,不难理解。
因为以太网线路上按 “Big Endian” 字节序传送报文(也就是最高字节先传送,关于字节序请参考相关文档),而比特序是”Little Endian”(也就是最低位先传送)。
注意图上的第 47bit,这一位表示 MAC 地址是全球唯一地址还是本地地址,0 表示全球唯一地址,1 表示本地唯一地址。这一位也叫 G/L 位。
对于网络设备上固化的 MAC 地址,因为它唯一标识这个设备,所以只能是单播地址,也就是 MAC 帧里面的 Source 地址第 48 位只能 0。
我们常说有 2 的 48 次方个 MAC 地址可供网络设备使用,这些地址可以多到给地球上每一粒沙子分配一个地址,其实这个数量要打折扣的,因为 MAC 地址虽然有这么多,但真正用在网卡上并且全球唯一的只有 2 的 46 次方个:第 48bit 一定是 0,第 47bit 一定是 0。
这也就引出了一个有意思的现象:随便找一台 PC,观察一下它的网卡地址,第 1 字节的十六进制数一般是 4 的倍数;查看一下 IEEE 分配的 OUI(http://standards.ieee.org/develop/regauth/oui/oui.txt ),第 1 字节的十六进制数也一般是 4 的倍数(早期以太网没有本地地址的概念,所以分配的 OUI 里面 G/L bit 也可能是 1),这种情况下就不是 4 的倍数了,但肯定是 2 的倍数,因为第 48 位只能是 0。
关于组播地址,有这么个误解:MAC 地址第 1 字节必须是 0x01 才表示组播地址,连 TCP/IP 详解上也这么说(见中文版 12.4.2 第一段)。IEEE 802.3 里面已经明确说明了只要第 48bit 是 1 就表示组播地址,所以无论 MAC 地址第 1 字节是 0x01、0xC1 或者是 0x33 都表示这个 MAC 地址是组播地址(以 0x33 开头的表示 IPV6 对应的二层组播地址)。之所以有这样的误解,是因为到目前为止,大部分组播 MAC 地址的第 1 字节都是 0x01。如:
01-80-C2-00-00-00(STP 协议使用)
01-80-C2-00-00-01(MAC Control 的 PAUSE 帧使用)
01-80-C2-00-00-02(Slow Protocol: 802.3ah OAM/ LACP 协议都用这个地址,这个地址很有故事,有多少软件处理这个地址会出问题啊!)
01-00-5E-xx-xx-xx(IP 组播地址对应的二层组播地址)。
目标 MAC 是组播 MAC 地址的以太网帧,只有交换机才会接收,而普通终端设备不会接收。
之所以大部分组播地址都以 01-80-C2 和 01-00-5E 开头,那是因为使用这些组播地址的协议都是带头大哥 IEEE 和 IANA 名下的,它们的 OUI 分别是 00-80-C2 和 00-00-5E 是,变成组播地址就是 01-80-C2 和 01-00-5E 了,当然,除了带头大哥霸占的这些组播地址,还有 01-00-0C-CC-CC-CC 这样的地址,这个地址是 Cisco 霸占的,Cisco 的 OUI 是 00-00-0C。
===========
主机网卡应该接收的数据帧:1. 目标 MAC 是自己的单播帧2. 广播帧3. 加入组播对应的组播帧
让网卡不检查包的接收方地址,不管是不是自己的包都统统接收下来,这种模式就叫做混杂模式。
linux 系统中网卡驱动收到报文后会检查报文的目的 mac 地址,区分广播,组播,和单播。如果是单播报文,则比较报文的目的 mac 地址是否和本网卡的 mac 一样,如果不一样则设置该报文为 PACKET_OTHERHOST。在 ip_rcv 函数中将 PACKET_OTHERHOST 类型的报文直接丢弃。所以说混杂模式下网卡收到不是自己 (仅限于本网卡)mac 的报文,只会在链路层处理,不会到网络层。详细分析可以参考文档:https://segmentfault.com/a/1190000021291692
ifconfig eth1 promisc ------ 开启混杂模式ifconfig eth1 -promisc ------ 关闭混杂模式ifconfig eth1 | grep PROMISC ------ 查看是否开启混杂模式
ip link set eth1 promisc on ------ 开启混杂模式ip link set eth1 promisc off ------ 关闭混杂模式ip link show eth1 | grep PROMISC ------ 查看是否开启混杂模式
以太网是载波侦听(CSMA/CD)。什么意思。通俗一点讲就是 “一个人在点到,大家都在听,点到自己才回答,没有点自己别吭声”。它是一种广播链路,共享信道方式。

2、网络包的过滤特性,过滤分两层,首先是硬件过滤(HW Filter),随后是软件过滤 (SW Filter)。上图中主机 B,C,D 拒绝是指硬件过滤。它过滤判断条件是 MAC 地址是否匹配,针对的是 MAC 地址,属于 OSI 第二层 -- 链路层的处理。 软件过滤判断条件是 ip 地址是否匹配。属于 OSI 协议分层里面的第三层过滤。正是因为一些原来不会产生应答而在混杂模式下却会产生应答的差异。提供了检测混杂模式的手段。

上表是一个很经典的 linux 下过滤特性统计表格,其中 gr bit 是指 group bit,组播位。第一个字节的最低位为 1 的所有地址,例如 01-12-0f-00-00-02。当然广播地址 FF:FF:FF:FF:FF:FF 也属于组播的一种。其中最后两行在普通模式下没有应答,而在混杂模式下有应答。所以可以利用最后两行来检测混杂模式。具体检测时候填充的 MAC 地址如下表。使用红圈两行即可。

最后两行属于多播地址范围(00:00:5e:00:00:00 - 00:00:5e:7f:ff:ff),参照上表,目的地址使用 FF:FF:FF:FF:FF:FE 或 FF:FF:00:00:00:00 即可不分 windows 还是 linux,探测出是否开启了混杂模式。 3、最后一步就是构造测试包,目前 linux 系统好像没有现成的可以构造目的地址的工具,需要自己写程序或使用第三方工具。可以构造一个 arp 包或者 ip 包,设置目的 mac 地址为上表红圈中地址即可。