# P2P protocol tests for various messages # Copyright (c) 2014, Jouni Malinen # # This software may be distributed under the terms of the BSD license. # See README for more details. import binascii import struct import time import logging logger = logging.getLogger() import hostapd from test_p2p_persistent import form from test_p2p_persistent import invite MGMT_SUBTYPE_PROBE_REQ = 4 MGMT_SUBTYPE_ACTION = 13 ACTION_CATEG_PUBLIC = 4 P2P_GO_NEG_REQ = 0 P2P_GO_NEG_RESP = 1 P2P_GO_NEG_CONF = 2 P2P_INVITATION_REQ = 3 P2P_INVITATION_RESP = 4 P2P_DEV_DISC_REQ = 5 P2P_DEV_DISC_RESP = 6 P2P_PROV_DISC_REQ = 7 P2P_PROV_DISC_RESP = 8 P2P_ATTR_STATUS = 0 P2P_ATTR_MINOR_REASON_CODE = 1 P2P_ATTR_CAPABILITY = 2 P2P_ATTR_DEVICE_ID = 3 P2P_ATTR_GROUP_OWNER_INTENT = 4 P2P_ATTR_CONFIGURATION_TIMEOUT = 5 P2P_ATTR_LISTEN_CHANNEL = 6 P2P_ATTR_GROUP_BSSID = 7 P2P_ATTR_EXT_LISTEN_TIMING = 8 P2P_ATTR_INTENDED_INTERFACE_ADDR = 9 P2P_ATTR_MANAGEABILITY = 10 P2P_ATTR_CHANNEL_LIST = 11 P2P_ATTR_NOTICE_OF_ABSENCE = 12 P2P_ATTR_DEVICE_INFO = 13 P2P_ATTR_GROUP_INFO = 14 P2P_ATTR_GROUP_ID = 15 P2P_ATTR_INTERFACE = 16 P2P_ATTR_OPERATING_CHANNEL = 17 P2P_ATTR_INVITATION_FLAGS = 18 P2P_ATTR_OOB_GO_NEG_CHANNEL = 19 P2P_ATTR_VENDOR_SPECIFIC = 221 P2P_SC_SUCCESS = 0 P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1 P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2 P2P_SC_FAIL_LIMIT_REACHED = 3 P2P_SC_FAIL_INVALID_PARAMS = 4 P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5 P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6 P2P_SC_FAIL_NO_COMMON_CHANNELS = 7 P2P_SC_FAIL_UNKNOWN_GROUP = 8 P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9 P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10 P2P_SC_FAIL_REJECTED_BY_USER = 11 WSC_ATTR_CONFIG_METHODS = 0x1008 WLAN_EID_SSID = 0 WLAN_EID_SUPP_RATES = 1 WLAN_EID_VENDOR_SPECIFIC = 221 def ie_ssid(ssid): return struct.pack("HHH", WSC_ATTR_CONFIG_METHODS, 2, methods) def p2p_attr_status(status=P2P_SC_SUCCESS): return struct.pack("HH', 0x1011, len(name)) +name def p2p_attr_group_id(addr, ssid): val = struct.unpack('6B', binascii.unhexlify(addr.replace(':',''))) t = (P2P_ATTR_GROUP_ID, 6 + len(ssid)) + val return struct.pack(' 2: (id,elen) = struct.unpack('BB', pos[0:2]) pos = pos[2:] if elen > len(pos): raise Exception("Truncated IE in P2P Public Action frame (elen=%d left=%d)" % (elen, len(pos))) if id == WLAN_EID_VENDOR_SPECIFIC: if elen < 4: raise Exception("Too short vendor specific IE in P2P Public Action frame (elen=%d)" % elen) (oui1,oui2,oui3,subtype) = struct.unpack('BBBB', pos[0:4]) if oui1 == 0x50 and oui2 == 0x6f and oui3 == 0x9a and subtype == 9: if 'p2p' in p2p: p2p['p2p'] += pos[4:elen] else: p2p['p2p'] = pos[4:elen] if oui1 == 0x00 and oui2 == 0x50 and oui3 == 0xf2 and subtype == 4: p2p['wsc'] = pos[4:elen] pos = pos[elen:] if len(pos) > 0: raise Exception("Invalid element in P2P Public Action frame") if 'p2p' in p2p: p2p['p2p_attrs'] = {} pos = p2p['p2p'] while len(pos) >= 3: (id,alen) = struct.unpack(' len(pos): logger.info("P2P payload: " + binascii.hexlify(p2p['p2p'])) raise Exception("Truncated P2P attribute in P2P Public Action frame (alen=%d left=%d p2p-payload=%d)" % (alen, len(pos), len(p2p['p2p']))) p2p['p2p_attrs'][id] = pos[0:alen] pos = pos[alen:] if P2P_ATTR_STATUS in p2p['p2p_attrs']: p2p['p2p_status'] = struct.unpack('B', p2p['p2p_attrs'][P2P_ATTR_STATUS])[0] if 'wsc' in p2p: p2p['wsc_attrs'] = {} pos = p2p['wsc'] while len(pos) >= 4: (id,alen) = struct.unpack('>HH', pos[0:4]) pos = pos[4:] if alen > len(pos): logger.info("WSC payload: " + binascii.hexlify(p2p['wsc'])) raise Exception("Truncated WSC attribute in P2P Public Action frame (alen=%d left=%d wsc-payload=%d)" % (alen, len(pos), len(p2p['wsc']))) p2p['wsc_attrs'][id] = pos[0:alen] pos = pos[alen:] return p2p def test_p2p_msg_empty(dev, apdev): """P2P protocol test: empty P2P Public Action frame""" dst, src, hapd, channel = start_p2p(dev, apdev) msg = p2p_hdr(dst, src) hapd.mgmt_tx(msg) def test_p2p_msg_invitation_req(dev, apdev): """P2P protocol tests for invitation request processing""" dst, src, hapd, channel = start_p2p(dev, apdev) # Empty P2P Invitation Request (missing dialog token) msg = p2p_hdr(dst, src, type=P2P_INVITATION_REQ, dialog_token=None) hapd.mgmt_tx(msg) dialog_token = 0 # Various p2p_parse() failure cases due to invalid attributes # Too short attribute header dialog_token += 1 msg = p2p_hdr(dst, src, type=P2P_INVITATION_REQ, dialog_token=dialog_token) attrs = struct.pack("