Developing lightweight computation at the DSG edge

Commit fd36f16c authored by Pau Escrich's avatar Pau Escrich
Browse files

- Add multicast rate

- Add 802.11 auto mode
- Add reghack packet
- Change default CC to US (reghacked)
- Disable b6m by default
- Small improvements in the wireless module
parent d94713ed
......@@ -43,7 +43,7 @@ config 'qmp' 'node'
config 'qmp' 'services'
option vpn 0
option captive_portal 0
option b6m 1
option b6m 0
option libremap 1
option gwck 1
option auto_upgrade 0
......@@ -87,7 +87,7 @@ config 'qmp' 'roaming'
# -----------------------------
config 'qmp' 'networks'
# DNS servers which will be configured.
option dns '141.1.1.1 85.126.4.170 202.83.95.227'
option dns '208.67.222.222 85.126.4.170 202.83.95.227'
# LAN address and netmask (will be assigned to br-lan).
option lan_address '172.30.22.1'
......@@ -127,6 +127,7 @@ config 'qmp' 'networks'
# -----------------------------
config 'qmp' 'wireless'
option driver 'mac80211'
option country 'SP'
option country 'US'
option bssid '02:CA:FF:EE:BA:BE'
option mrate '6000'
......@@ -161,12 +161,15 @@ qmp_configure_wifi_device() {
} || {
m11b="$(echo $channel_raw | tr -d [0-9]+-)"
m11n="$($QMPINFO modes $device | grep -c n)"
[ -n "$m11b" -o $m11n = 0 ] && {
# Device is not 11n compatible or mode 11b is forced
[ -n "$m11b" ] && {
# Mode 11b is forced
htmode=""
mode11="b"
} || {
} || [ $m11n -eq 0 ] && {
# Device is not 11n compatible
htmode=""
mode11="auto"
} || {
# Device is 11n compatible
htmode="HT20"
mode11="n"
......@@ -199,6 +202,7 @@ qmp_configure_wifi_device() {
echo "Name $name"
echo "HTmode $htmode"
echo "11mode $mode11"
echo "Mrate $mrate"
echo "------------------------"
local vap=0
......@@ -219,6 +223,7 @@ qmp_configure_wifi_device() {
-e s/"#QMP_MAC"/"$mac"/ \
-e s/"#QMP_CHANNEL"/"$channel"/ \
-e s/"#QMP_COUNTRY"/"$country"/ \
-e s/"#QMP_MRATE"/"$mrate"/ \
-e s/"#QMP_HTMODE"/"$htmode"/ \
-e s/"#QMP_TXPOWER"/"$txpower"/ > $TMP/qmp_wifi_device
......@@ -233,7 +238,6 @@ qmp_configure_wifi_device() {
-e s/"#QMP_NETWORK"/"$network"/ \
-e s/"#QMP_ENC"/"$encrypt"/ \
-e s/"#QMP_KEY"/"$key"/ \
-e s/"#QMP_MRATE"/"$mrate"/ \
-e s/"#QMP_MODE"/"$mode"/ > $TMP/qmp_wifi_iface
......@@ -244,11 +248,10 @@ qmp_configure_wifi_device() {
-e s/"#QMP_RADIO"/"$radio"/ \
-e s/"#QMP_DEVICE"/"${device}ap"/ \
-e s/"#QMP_IFNAME"/"${device}ap"/ \
-e s/"#QMP_SSID"/"$name"/ \
-e s/"#QMP_SSID"/"${name}-AP"/ \
-e s/"#QMP_NETWORK"/"lan"/ \
-e s/"#QMP_ENC"/"$encrypt"/ \
-e s/"#QMP_KEY"/"$key"/ \
-e s/"#QMP_MRATE"/"$mrate"/ \
-e s/"#QMP_MODE"/"ap"/ >> $TMP/qmp_wifi_iface
}
......
wireless.#QMP_RADIO=wifi-device
wireless.#QMP_RADIO.type=mac80211
wireless.#QMP_RADIO.macaddr=#QMP_MAC
wireless.#QMP_RADIO.channel=#QMP_CHANNEL
wireless.#QMP_RADIO.country=#QMP_COUNTRY
wireless.#QMP_RADIO.hwmode=auto
wireless.#QMP_RADIO.txpower=#QMP_TXPOWER
wireless.#QMP_RADIO.mcast_rate=#QMP_MRATE
......@@ -5,3 +5,4 @@ wireless.#QMP_RADIO.channel=#QMP_CHANNEL
wireless.#QMP_RADIO.country=#QMP_COUNTRY
wireless.#QMP_RADIO.hwmode=11b
wireless.#QMP_RADIO.txpower=#QMP_TXPOWER
wireless.#QMP_RADIO.mcast_rate=#QMP_MRATE
......@@ -8,6 +8,7 @@ wireless.#QMP_RADIO.htmode=#QMP_HTMODE
wireless.#QMP_RADIO.txpower=#QMP_TXPOWER
wireless.#QMP_RADIO.noscan=1
wireless.#QMP_RADIO.distance=5000
wireless.#QMP_RADIO.mcast_rate=#QMP_MRATE
list wireless.#QMP_RADIO.ht_capab=SHORT-GI-20
list wireless.#QMP_RADIO.ht_capab=SHORT-GI-40
list wireless.#QMP_RADIO.ht_capab=RX-STBC1
......
......@@ -51,6 +51,9 @@ country = s_wireless_main:option(Value,"country", translate("Country"))
-- BSSID
bssid = s_wireless_main:option(Value,"bssid","BSSID")
-- MRATE
mrate = s_wireless_main:option(Value,"mrate",translate("Multicast rate"))
-- Button Rescan Wifi devices
confwifi = s_wireless_main:option(Button, "_confwifi", translate("Reconfigure"),
translate("Rescan and reconfigure all devices. <br/>Use it just in case you have added or changed a device."))
......
#
# Copyright (C) 2006-2013 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=reghack
PKG_VERSION:=20131203
PKG_RELEASE=1
include $(INCLUDE_DIR)/package.mk
define Package/$(PKG_NAME)/template
TITLE:=Reg domain unlocker
SECTION:=net
CATEGORY:=qMp
MAINTAINER:=Satoshi Nakamoto
endef
define Package/$(PKG_NAME)
$(call Package/$(PKG_NAME)/template)
TITLE:=Regulatory domain unlocker
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
$(call Build/Prepare/Default)
endef
define Build/Compile
$(TARGET_CC) -o $(PKG_BUILD_DIR)/reghack $(PKG_BUILD_DIR)/reghack.c
$(HOSTCC) -o $(STAGING_DIR_HOST)/bin/reghack $(PKG_BUILD_DIR)/reghack.c
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/reghack $(1)/usr/bin/reghack
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
for module in ath cfg80211 ; do
cp "$$IPKG_INSTROOT"/lib/modules/*/$${module}.ko /tmp/
reghack /tmp/$${module}.ko && \
mv /tmp/$${module}.ko "$$IPKG_INSTROOT"/lib/modules/*/
done
exit 0
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
/*
* reghack - Utility to binary-patch the embedded mac80211 regulatory rules.
*
* Copyright (C) 2012-2013 Jo-Philipp Wich <xm@subsignal.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <byteswap.h>
#include <limits.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/mman.h>
static int need_byteswap = 0;
enum nl80211_dfs_regions {
NL80211_DFS_UNSET = 0,
NL80211_DFS_FCC = 1
};
struct ieee80211_freq_range {
uint32_t start_freq_khz;
uint32_t end_freq_khz;
uint32_t max_bandwidth_khz;
};
struct ieee80211_power_rule {
uint32_t max_antenna_gain;
uint32_t max_eirp;
};
struct ieee80211_reg_rule {
struct ieee80211_freq_range freq_range;
struct ieee80211_power_rule power_rule;
uint32_t flags;
};
struct ieee80211_regdomain_old {
uint32_t n_reg_rules;
char alpha2[2];
uint8_t dfs_region;
struct ieee80211_reg_rule reg_rules[1];
};
struct ieee80211_regdomain {
uint32_t n_reg_rules;
char alpha2[2];
enum nl80211_dfs_regions dfs_region;
struct ieee80211_reg_rule reg_rules[1];
};
#define MHZ_TO_KHZ(freq) ((freq) * 1000)
#define KHZ_TO_MHZ(freq) ((freq) / 1000)
#define DBI_TO_MBI(gain) ((gain) * 100)
#define MBI_TO_DBI(gain) ((gain) / 100)
#define DBM_TO_MBM(gain) ((gain) * 100)
#define MBM_TO_DBM(gain) ((gain) / 100)
#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
{ \
.freq_range.start_freq_khz = MHZ_TO_KHZ(start), \
.freq_range.end_freq_khz = MHZ_TO_KHZ(end), \
.freq_range.max_bandwidth_khz = MHZ_TO_KHZ(bw), \
.power_rule.max_antenna_gain = DBI_TO_MBI(gain),\
.power_rule.max_eirp = DBM_TO_MBM(eirp), \
.flags = reg_flags, \
}
#define REG_MATCH(code, num, dfs, rule) \
{ \
.alpha2 = code, \
.dfs_region = dfs, \
.n_reg_rules = num, \
.reg_rules = { \
rule \
} \
}
struct search_regdomain {
const char *desc;
struct ieee80211_regdomain reg;
struct ieee80211_regdomain_old old;
};
static const struct search_regdomain search_regdomains[] = {
/* cfg80211.ko matches */
{
.desc = "core world5 regdomain in cfg80211/reg.o",
.reg = REG_MATCH("00", 5, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 6, 20, 0))
}, {
.desc = "core world6 regdomain in cfg80211/reg.o",
.reg = REG_MATCH("00", 6, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 6, 20, 0))
}, {
.desc = "embedded 00 regdomain in cfg80211/regdb.o",
.reg = REG_MATCH("00", 5, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 3, 20, 0))
}, {
.desc = "embedded 00 regdomain in cfg80211/regdb.o",
.reg = REG_MATCH("00", 6, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 3, 20, 0))
}, {
.desc = "embedded US regdomain in cfg80211/regdb.o",
.reg = REG_MATCH("US", 6, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 3, 27, 0))
}, {
.desc = "embedded US regdomain in cfg80211/regdb.o",
.reg = REG_MATCH("US", 7, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 3, 27, 0))
}, {
.desc = "embedded US regdomain in cfg80211/regdb.o",
.reg = REG_MATCH("US", 7, NL80211_DFS_FCC, REG_RULE(2402, 2472, 40, 3, 27, 0))
},
/* ath.ko matches */
{
.desc = "ath world regdomain with 3 rules in ath/regd.o",
.reg = REG_MATCH("99", 3, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 0, 20, 0))
}, {
.desc = "ath world regdomain with 4 rules in ath/regd.o",
.reg = REG_MATCH("99", 4, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 0, 20, 0))
}, {
.desc = "ath world regdomain with 5 rules in ath/regd.o",
.reg = REG_MATCH("99", 5, NL80211_DFS_UNSET, REG_RULE(2402, 2472, 40, 0, 20, 0))
}
};
struct search_insn {
const char *desc;
const uint16_t machine;
const uint32_t search;
const uint32_t replace;
const uint32_t mask;
};
static const struct search_insn search_insns[] = {
/* radar frequency check */
{
.desc = "ath_is_radar_freq() MIPS opcode in ath/regd.o",
.machine = 0x0008, /* MIPS */
.search = 0x2400eb74, /* addiu rX, rY, -5260 */
.replace = 0x24000000, /* addiu rX, rY, 0 */
.mask = 0xfc00ffff
},
{
.desc = "ath_is_radar_freq() PPC opcode in ath/regd.o",
.machine = 0x0014, /* PPC */
.search = 0x3800eb74, /* addi rX, rY, -5260 */
.replace = 0x38000000, /* addi rX, rY, 0 */
.mask = 0xfc00ffff
},
};
static void check_endianess(unsigned char *elf_hdr)
{
int self_is_be = (htonl(42) == 42);
int elf_is_be = (elf_hdr[5] == 2);
if (self_is_be != elf_is_be)
{
need_byteswap = 1;
printf("Byte swapping needed (utility %s endian, module %s endian)\n",
self_is_be ? "big" : "low",
elf_is_be ? "big" : "low");
}
}
static void bswap_rule(struct ieee80211_reg_rule *r)
{
r->freq_range.start_freq_khz = bswap_32(r->freq_range.start_freq_khz);
r->freq_range.end_freq_khz = bswap_32(r->freq_range.end_freq_khz);
r->freq_range.max_bandwidth_khz = bswap_32(r->freq_range.max_bandwidth_khz);
r->power_rule.max_antenna_gain = bswap_32(r->power_rule.max_antenna_gain);
r->power_rule.max_eirp = bswap_32(r->power_rule.max_eirp);
r->flags = bswap_32(r->flags);
}
static int patch_regdomain(struct ieee80211_regdomain *pos,
const struct ieee80211_regdomain *comp)
{
struct ieee80211_reg_rule r2 = REG_RULE(2400, 2484, 40, 0, 30, 0);
struct ieee80211_reg_rule r5 = REG_RULE(5140, 5860, 40, 0, 30, 0);
struct ieee80211_regdomain pattern = *comp;
struct ieee80211_regdomain_old *pos2 = (struct ieee80211_regdomain_old *)pos;
struct ieee80211_regdomain_old pattern2 = { };
if (need_byteswap)
{
bswap_rule(&pattern.reg_rules[0]);
pattern.dfs_region = bswap_32(pattern.dfs_region);
pattern.n_reg_rules = bswap_32(pattern.n_reg_rules);
}
pattern2.dfs_region = pattern.dfs_region;
pattern2.n_reg_rules = pattern.n_reg_rules;
memcpy(&pattern2.alpha2, &pattern.alpha2, sizeof(pattern2.alpha2));
memcpy(&pattern2.reg_rules, &pattern.reg_rules, sizeof(pattern2.reg_rules));
if (!memcmp(pos, &pattern, sizeof(pattern)))
{
pos->reg_rules[0] = r2;
pos->reg_rules[1] = r5;
pos->n_reg_rules = 2;
pos->dfs_region = 0;
if (need_byteswap)
{
bswap_rule(&pos->reg_rules[0]);
bswap_rule(&pos->reg_rules[1]);
pos->n_reg_rules = bswap_32(pos->n_reg_rules);
}
return 0;
}
else if (!memcmp(pos2, &pattern2, sizeof(pattern2)))
{
pos2->reg_rules[0] = r2;
pos2->reg_rules[1] = r5;
pos2->n_reg_rules = 2;
pos2->dfs_region = 0;
if (need_byteswap)
{
bswap_rule(&pos2->reg_rules[0]);
bswap_rule(&pos2->reg_rules[1]);
pos2->n_reg_rules = bswap_32(pos2->n_reg_rules);
}
return 0;
}
return 1;
}
static uint16_t check_ath_ko(unsigned char *elf_hdr, const char *filename)
{
uint16_t type = *(uint16_t *)(elf_hdr + 18);
const char *file = strrchr(filename, '/');
if (!file)
file = filename;
else
file++;
if (need_byteswap)
type = bswap_16(type);
if (!strcmp(file, "ath.ko"))
return type;
return 0;
}
static int patch_insn(uint32_t *pos, const struct search_insn *insn)
{
uint32_t cmp = need_byteswap ? bswap_32(*pos) : *pos;
if ((cmp & insn->mask) == insn->search)
{
*pos = need_byteswap ? bswap_32(insn->replace | (cmp & ~insn->mask))
: insn->replace | (cmp & ~insn->mask);
return 0;
}
return 1;
}
static int tryopen(const char *path, int *size, void **map)
{
int fd;
struct stat s;
if (stat(path, &s))
{
perror("stat()");
return -1;
}
if ((fd = open(path, O_RDWR)) == -1)
{
perror("open()");
return -2;
}
*size = s.st_size;
*map = mmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (*map == MAP_FAILED)
{
close(fd);
perror("mmap()");
return -3;
}
return fd;
}
int main(int argc, char **argv)
{
int i, j, fd, sz;
int found = 0;
uint16_t ath_ko_machine = 0;
void *map;
char *tmp = NULL, cmd[PATH_MAX * 2 + 4];
if (argc < 2)
{
printf("Usage: %s module.ko\n", argv[0]);
exit(1);
}
fd = tryopen(argv[1], &sz, &map);
if (fd == -3)
{
printf("Memory mapping failed (missing fs support?), retrying from tmpfs\n");
tmp = tmpnam(NULL);
sprintf(cmd, "cp %s %s", argv[1], tmp);
system(cmd);
fd = tryopen(tmp, &sz, &map);
}
if (fd < 0)
{
if (tmp)
unlink(tmp);
exit(1);
}
check_endianess(map);
ath_ko_machine = check_ath_ko(map, argv[1]);
for (i = 0; i < (sz - sizeof(search_regdomains[0].reg)); i += sizeof(uint32_t))
{
if (ath_ko_machine)
{
for (j = 0; j < sizeof(search_insns)/sizeof(search_insns[0]); j++)
{
if (search_insns[j].machine != ath_ko_machine)
continue;
if (!patch_insn(map + i, &search_insns[j]))
{
printf("Patching @ 0x%08x: %s\n", i, search_insns[j].desc);
found = 1;
}
}
}
for (j = 0; j < (sizeof(search_regdomains)/sizeof(search_regdomains[0])); j++)
{
if (!patch_regdomain(map + i, &search_regdomains[j].reg))
{
printf("Patching @ 0x%08x: %s\n", i, search_regdomains[j].desc);
found = 1;
}
}
}
if (munmap(map, sz))
{
perror("munmap()");
exit(1);
}
if (tmp)
{
if (found)
{
sprintf(cmd, "cp %s %s", tmp, argv[1]);
system(cmd);
}
unlink(tmp);
}
close(fd);
if (!found)
{
printf("Unable to find regulatory rules (already patched?)\n");
exit(1);
}
return 0;
}
#!/bin/sh
hackMe="ath cfg80211"
cd /tmp
for module in ${hackMe}
do
cp /lib/modules/*/${module}.ko /tmp
/usr/bin/reghack ${module}.ko
mv ${module}.ko /lib/modules/*/
done
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment