Nice hardware, but no channel 13
Last week I got myself a TP-Link TL-WR1043ND and pressed it into service as a smart 5-port gigabit switch (with VLAN capabilities) and wireless-N bridge. It is a fine piece of hardware and unbelievably cheap. Best of all, you can install the OpenWRT linux distribution on it. OpenWRT doesn’t target the inexperienced, but it is very customizable, offers a fair amount of documentation, and the build system seems very worthy of giving it a spin.
However. I noticed I couldn’t select a wireless channel >11. That’s odd, because over here in Europe we’re allowed to use the frequencies of channel 12 and 13, too.
Here’s what dmesg told me:
cfg80211: Calling CRDA to update world regulatory domain
cfg80211: World regulatory domain updated:
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
(2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
(2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
(5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
(5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
ath: EEPROM regdomain: 0x0
ath: EEPROM indicates default country code should be used
ath: doing EEPROM country->regdmn map search
ath: country maps to regdmn code: 0x3a
ath: Country alpha2 being used: US
ath: Regpair used: 0x3a
phy0: Selected rate control algorithm 'ath9k_rate_control'
phy0: Atheros AR9100 MAC/BB Rev:0 AR2133 RF Rev:a2 mem=0xb80c0000, irq=2
cfg80211: Calling CRDA for country: US
cfg80211: Regulatory domain changed to country: US
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2700 mBm)
(5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 1700 mBm)
(5250000 KHz - 5330000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
(5490000 KHz - 5600000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
(5650000 KHz - 5710000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
(5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 3000 mBm)
So why does the system think I am in the US? And how can I tell it that I’m actually in the Netherlands? At first glance, it should be as easy as iw reg set NL. Result:
cfg80211: Calling CRDA for country: NL
cfg80211: Regulatory domain changed to country: NL
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm)
(5170000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)
(5250000 KHz - 5330000 KHz @ 40000 KHz), (N/A, 2000 mBm)
(5490000 KHz - 5710000 KHz @ 40000 KHz), (N/A, 2700 mBm)
Looks about right, doesn’t it? Because 2482000 > 2472000. 2472 KHz is the upper bound of the 22 KHz wide channel 11. Likewise, 2482 KHz is the upper bound of channel 13. So am I all good for channel 13 now? Turns out I am not. iwlist wlan0 channel says:
wlan0 11 channels in total; available frequencies :
Channel 01 : 2.412 GHz
Channel 02 : 2.417 GHz
Channel 03 : 2.422 GHz
Channel 04 : 2.427 GHz
Channel 05 : 2.432 GHz
Channel 06 : 2.437 GHz
Channel 07 : 2.442 GHz
Channel 08 : 2.447 GHz
Channel 09 : 2.452 GHz
Channel 10 : 2.457 GHz
Channel 11 : 2.462 GHz
Current Frequency=2.452 GHz (Channel 9)
The wherefore and the why. And the how.
No channel 13. Wut? I found this informative mailing list post detailing what’s happening here. Basically, the kernel first loads the rules for the ‘world’ domain. On planet Earth, no countries exist that allow you to go beyond these frequencies (for domestic wifi). But many countries have additional restrictions. In Japan, you can use channel 14, in Europe you can’t. You can use 12 and 13 though, which in the US you can’t.
The kernel (well, the “ath” driver) then proceeds to look for any hints from the hardware. In my case the value burned into the hardware EEPROM is 0×0. That’s a value, which, per the Atheros specs, should map to the US. The kernel calls a userspace program crda to get the list of allowed frequencies and signal strenghts for the US.
After this has been done, you can do iw reg set FOO until you drop but you wont be able to go beyond the limits set previously.
The weird thing with radio hardware is that not only the users are subject to regulation, the sellers are too. You can’t sell non-compliant radio hardware. Now, the wifi chip manufacturers do not physically limit a chip intended for sale in the US to channels 1-11. Rather, they mass produce chips and then the equipment manufacturers are supposed to configure the chip in compliance with its target market. (As if you’d never take your equipment to Japan).
As I understand it, TP-Link messed up here.
Compare the above setup with what happens on my laptop’s Atheros chip:
ath: EEPROM regdomain: 0x65 ath: EEPROM indicates we should expect a direct regpair map ath: Country alpha2 being used: 00 ath: Regpair used: 0x65
Looking at the Linux 2.6.35 sourcecode in drivers/net/wireless/ath/regd_common.h you’ll see that 0×65 maps to WOR5_ETSIC, which holds rules for compliance with EU regulation. Which I suppose is right since I’ve bought that laptop in the EU. But my TP-link comes out as FCC3_FCCA — that’s FCC-land, the US.
Fixing it
So either patch the kernel’s mappings, or patch the userspace ‘crda‘ program to supply a modified list of allowed frequencies for the ‘US’. I chose the latter. Reading a bit more about this program and its database, it didn’t appear I could fix it easily — the database is digitally signed and the public key needs to be known to the crda program at compile-time. No problem on a Gentoo system, but the target system was OpenWRT. On a MIPS machine. That meant cross-compiling, so I proceeded by downloading the OpenWRT dev environment for the Backfire release, and had a look around. And whaddayaknow, package/crda/patches/101-make_crypto_use_optional.patch made me hope that signature checking wasn’t even compiled in! On my OpenWRT box:
root@t33t:~# ldd /sbin/crda libnl-tiny.so => /usr/lib/libnl-tiny.so (0x2aabe000) libm.so.0 => /lib/libm.so.0 (0x2aad6000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x2aaff000) libc.so.0 => /lib/libc.so.0 (0x2ab1f000) ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x2aaa8000)
(Don’t you just love it). Now I don’t know a lot about embedded environments and uclibc, but I don’t see any libcrypto.so or libgcrypt.so in there. It looks like I can just supply any old unsigned database. More reading of documentation, some compiling of tools.
regdbdump /usr/lib64/crda/regulatory.bin gives me an editable version of the database. I didn’t feel like limiting myself, so I replaced this:
country 00: (2402.000 - 2472.000 @ 40.000), (3.00, 20.00) (2457.000 - 2482.000 @ 20.000), (3.00, 20.00), PASSIVE-SCAN, NO-IBSS (2474.000 - 2494.000 @ 20.000), (3.00, 20.00), NO-OFDM, PASSIVE-SCAN, NO-IBSS (5170.000 - 5250.000 @ 40.000), (3.00, 20.00), PASSIVE-SCAN, NO-IBSS (5735.000 - 5835.000 @ 40.000), (3.00, 20.00), PASSIVE-SCAN, NO-IBSS country US: (2402.000 - 2472.000 @ 40.000), (3.00, 27.00) (5170.000 - 5250.000 @ 40.000), (3.00, 17.00) (5250.000 - 5330.000 @ 40.000), (3.00, 20.00), DFS (5490.000 - 5600.000 @ 40.000), (3.00, 20.00), DFS (5650.000 - 5710.000 @ 40.000), (3.00, 20.00), DFS (5735.000 - 5835.000 @ 40.000), (3.00, 30.00)
with this:
country 00: (2402.000 - 2494.000 @ 40.000), (N/A, 30.00) (4910.000 - 5835.000 @ 40.000), (N/A, 30.00) country US: (2402.000 - 2494.000 @ 40.000), (N/A, 30.00) (4910.000 - 5835.000 @ 40.000), (N/A, 30.00)
and then I converted the database to its binary form with db2bin.py which one can find in the wireless-regdb source code releases. Copied the new database over to my OpenWRT machine, restarted it, dmesg, presto:
cfg80211: Calling CRDA to update world regulatory domain
cfg80211: World regulatory domain updated:
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2494000 KHz @ 40000 KHz), (N/A, 3000 mBm)
(4910000 KHz - 5835000 KHz @ 40000 KHz), (N/A, 3000 mBm)
ath: EEPROM regdomain: 0x0
ath: EEPROM indicates default country code should be used
ath: doing EEPROM country->regdmn map search
ath: country maps to regdmn code: 0x3a
ath: Country alpha2 being used: US
ath: Regpair used: 0x3a
phy0: Selected rate control algorithm 'ath9k_rate_control'
phy0: Atheros AR9100 MAC/BB Rev:0 AR2133 RF Rev:a2 mem=0xb80c0000, irq=2
cfg80211: Calling CRDA for country: US
cfg80211: Regulatory domain changed to country: US
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2494000 KHz @ 40000 KHz), (N/A, 3000 mBm)
(4910000 KHz - 5835000 KHz @ 40000 KHz), (N/A, 3000 mBm)
root@t33t:~# iwlist wlan0 channel
wlan0 14 channels in total; available frequencies :
Channel 01 : 2.412 GHz
Channel 02 : 2.417 GHz
Channel 03 : 2.422 GHz
Channel 04 : 2.427 GHz
Channel 05 : 2.432 GHz
Channel 06 : 2.437 GHz
Channel 07 : 2.442 GHz
Channel 08 : 2.447 GHz
Channel 09 : 2.452 GHz
Channel 10 : 2.457 GHz
Channel 11 : 2.462 GHz
Channel 12 : 2.467 GHz
Channel 13 : 2.472 GHz
Channel 14 : 2.484 GHz
Current Frequency=2.452 GHz (Channel 9)
Legality
This is a rather libertarian approach. Not legal on Earth, it doesn’t even comply with the ‘World’ regulatory domain. Yes, among other things, this gives you access to the ‘Japanese’ channel 14. The rules don’t prevent you from going totally EMP on your neighbourhood. (Your hardware does, though).
It’s now YOUR responsibility to comply with local regulations. If you look out the window and see an airliner perform a barrel roll, you know it’s time to iw reg set $YOURCOUNTRYCODE.
And remember, interference works both ways. The fact that your neighbours cannot use some frequencies doesn’t necessarily mean you’ll get good performance using those (frequencies I mean). It may well be that you’ll have lousy reception because other (possibly more powerful) equipment is legally being used on those channels. Just stick with your country’s regulations OK?
I kept the previous ‘US’ entry as ‘UX’ so I can still comply with US regulations if necessary. I hear they’re big on regulations in the US. Especially if it involves foreigners.
Tags: atheros, English, hack, linux, openwrt, wifi —



