1 package com.android.server.wifi.anqp; 2 3 import java.net.ProtocolException; 4 import java.nio.ByteBuffer; 5 import java.nio.ByteOrder; 6 import java.nio.charset.Charset; 7 import java.util.HashMap; 8 import java.util.Map; 9 10 /** 11 * ANQP related constants (802.11-2012) 12 */ 13 public class Constants { 14 15 public static final int NIBBLE_MASK = 0x0f; 16 public static final int BYTE_MASK = 0xff; 17 public static final int SHORT_MASK = 0xffff; 18 public static final long INT_MASK = 0xffffffffL; 19 public static final int BYTES_IN_SHORT = 2; 20 public static final int BYTES_IN_INT = 4; 21 public static final int BYTES_IN_EUI48 = 6; 22 23 public static final int HS20_PREFIX = 0x119a6f50; // Note that this is represented as a LE int 24 public static final int HS20_FRAME_PREFIX = 0x109a6f50; 25 public static final int UTF8_INDICATOR = 1; 26 27 public static final int ANQP_QUERY_LIST = 256; 28 public static final int ANQP_CAPABILITY_LIST = 257; 29 public static final int ANQP_VENUE_NAME = 258; 30 public static final int ANQP_EMERGENCY_NUMBER = 259; 31 public static final int ANQP_NWK_AUTH_TYPE = 260; 32 public static final int ANQP_ROAMING_CONSORTIUM = 261; 33 public static final int ANQP_IP_ADDR_AVAILABILITY = 262; 34 public static final int ANQP_NAI_REALM = 263; 35 public static final int ANQP_3GPP_NETWORK = 264; 36 public static final int ANQP_GEO_LOC = 265; 37 public static final int ANQP_CIVIC_LOC = 266; 38 public static final int ANQP_LOC_URI = 267; 39 public static final int ANQP_DOM_NAME = 268; 40 public static final int ANQP_EMERGENCY_ALERT = 269; 41 public static final int ANQP_TDLS_CAP = 270; 42 public static final int ANQP_EMERGENCY_NAI = 271; 43 public static final int ANQP_NEIGHBOR_REPORT = 272; 44 public static final int ANQP_VENDOR_SPEC = 56797; 45 46 public static final int HS_QUERY_LIST = 1; 47 public static final int HS_CAPABILITY_LIST = 2; 48 public static final int HS_FRIENDLY_NAME = 3; 49 public static final int HS_WAN_METRICS = 4; 50 public static final int HS_CONN_CAPABILITY = 5; 51 public static final int HS_NAI_HOME_REALM_QUERY = 6; 52 public static final int HS_OPERATING_CLASS = 7; 53 public static final int HS_OSU_PROVIDERS = 8; 54 public static final int HS_ICON_REQUEST = 10; 55 public static final int HS_ICON_FILE = 11; 56 57 public enum ANQPElementType { 58 ANQPQueryList, 59 ANQPCapabilityList, 60 ANQPVenueName, 61 ANQPEmergencyNumber, 62 ANQPNwkAuthType, 63 ANQPRoamingConsortium, 64 ANQPIPAddrAvailability, 65 ANQPNAIRealm, 66 ANQP3GPPNetwork, 67 ANQPGeoLoc, 68 ANQPCivicLoc, 69 ANQPLocURI, 70 ANQPDomName, 71 ANQPEmergencyAlert, 72 ANQPTDLSCap, 73 ANQPEmergencyNAI, 74 ANQPNeighborReport, 75 ANQPVendorSpec, 76 HSQueryList, 77 HSCapabilityList, 78 HSFriendlyName, 79 HSWANMetrics, 80 HSConnCapability, 81 HSNAIHomeRealmQuery, 82 HSOperatingclass, 83 HSOSUProviders, 84 HSIconRequest, 85 HSIconFile 86 } 87 88 private static final Map<Integer, ANQPElementType> sAnqpMap = new HashMap<Integer, ANQPElementType>(); 89 private static final Map<Integer, ANQPElementType> sHs20Map = new HashMap<Integer, ANQPElementType>(); 90 private static final Map<ANQPElementType, Integer> sRevAnqpmap = new HashMap<ANQPElementType, Integer>(); 91 private static final Map<ANQPElementType, Integer> sRevHs20map = new HashMap<ANQPElementType, Integer>(); 92 93 static { 94 sAnqpMap.put(ANQP_QUERY_LIST, ANQPElementType.ANQPQueryList); 95 sAnqpMap.put(ANQP_CAPABILITY_LIST, ANQPElementType.ANQPCapabilityList); 96 sAnqpMap.put(ANQP_VENUE_NAME, ANQPElementType.ANQPVenueName); 97 sAnqpMap.put(ANQP_EMERGENCY_NUMBER, ANQPElementType.ANQPEmergencyNumber); 98 sAnqpMap.put(ANQP_NWK_AUTH_TYPE, ANQPElementType.ANQPNwkAuthType); 99 sAnqpMap.put(ANQP_ROAMING_CONSORTIUM, ANQPElementType.ANQPRoamingConsortium); 100 sAnqpMap.put(ANQP_IP_ADDR_AVAILABILITY, ANQPElementType.ANQPIPAddrAvailability); 101 sAnqpMap.put(ANQP_NAI_REALM, ANQPElementType.ANQPNAIRealm); 102 sAnqpMap.put(ANQP_3GPP_NETWORK, ANQPElementType.ANQP3GPPNetwork); 103 sAnqpMap.put(ANQP_GEO_LOC, ANQPElementType.ANQPGeoLoc); 104 sAnqpMap.put(ANQP_CIVIC_LOC, ANQPElementType.ANQPCivicLoc); 105 sAnqpMap.put(ANQP_LOC_URI, ANQPElementType.ANQPLocURI); 106 sAnqpMap.put(ANQP_DOM_NAME, ANQPElementType.ANQPDomName); 107 sAnqpMap.put(ANQP_EMERGENCY_ALERT, ANQPElementType.ANQPEmergencyAlert); 108 sAnqpMap.put(ANQP_TDLS_CAP, ANQPElementType.ANQPTDLSCap); 109 sAnqpMap.put(ANQP_EMERGENCY_NAI, ANQPElementType.ANQPEmergencyNAI); 110 sAnqpMap.put(ANQP_NEIGHBOR_REPORT, ANQPElementType.ANQPNeighborReport); 111 sAnqpMap.put(ANQP_VENDOR_SPEC, ANQPElementType.ANQPVendorSpec); 112 113 sHs20Map.put(HS_QUERY_LIST, ANQPElementType.HSQueryList); 114 sHs20Map.put(HS_CAPABILITY_LIST, ANQPElementType.HSCapabilityList); 115 sHs20Map.put(HS_FRIENDLY_NAME, ANQPElementType.HSFriendlyName); 116 sHs20Map.put(HS_WAN_METRICS, ANQPElementType.HSWANMetrics); 117 sHs20Map.put(HS_CONN_CAPABILITY, ANQPElementType.HSConnCapability); 118 sHs20Map.put(HS_NAI_HOME_REALM_QUERY, ANQPElementType.HSNAIHomeRealmQuery); 119 sHs20Map.put(HS_OPERATING_CLASS, ANQPElementType.HSOperatingclass); 120 sHs20Map.put(HS_OSU_PROVIDERS, ANQPElementType.HSOSUProviders); 121 sHs20Map.put(HS_ICON_REQUEST, ANQPElementType.HSIconRequest); 122 sHs20Map.put(HS_ICON_FILE, ANQPElementType.HSIconFile); 123 124 for (Map.Entry<Integer, ANQPElementType> entry : sAnqpMap.entrySet()) { 125 sRevAnqpmap.put(entry.getValue(), entry.getKey()); 126 } 127 for (Map.Entry<Integer, ANQPElementType> entry : sHs20Map.entrySet()) { 128 sRevHs20map.put(entry.getValue(), entry.getKey()); 129 } 130 } 131 132 public static ANQPElementType mapANQPElement(int id) { 133 return sAnqpMap.get(id); 134 } 135 136 public static ANQPElementType mapHS20Element(int id) { 137 return sHs20Map.get(id); 138 } 139 140 public static Integer getANQPElementID(ANQPElementType elementType) { 141 return sRevAnqpmap.get(elementType); 142 } 143 144 public static Integer getHS20ElementID(ANQPElementType elementType) { 145 return sRevHs20map.get(elementType); 146 } 147 148 public static long getInteger(ByteBuffer payload, ByteOrder bo, int size) { 149 byte[] octets = new byte[size]; 150 payload.get(octets); 151 long value = 0; 152 if (bo == ByteOrder.LITTLE_ENDIAN) { 153 for (int n = octets.length - 1; n >= 0; n--) { 154 value = (value << Byte.SIZE) | (octets[n] & BYTE_MASK); 155 } 156 } 157 else { 158 for (byte octet : octets) { 159 value = (value << Byte.SIZE) | (octet & BYTE_MASK); 160 } 161 } 162 return value; 163 } 164 165 public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset) 166 throws ProtocolException { 167 return getPrefixedString(payload, lengthLength, charset, false); 168 } 169 170 public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset, 171 boolean useNull) throws ProtocolException { 172 if (payload.remaining() < lengthLength) { 173 throw new ProtocolException("Runt string: " + payload.remaining()); 174 } 175 return getString(payload, (int) getInteger(payload, ByteOrder.LITTLE_ENDIAN, 176 lengthLength), charset, useNull); 177 } 178 179 public static String getString(ByteBuffer payload, int length, Charset charset) 180 throws ProtocolException { 181 return getString(payload, length, charset, false); 182 } 183 184 public static String getString(ByteBuffer payload, int length, Charset charset, boolean useNull) 185 throws ProtocolException { 186 if (length > payload.remaining()) { 187 throw new ProtocolException("Bad string length: " + length); 188 } 189 if (useNull && length == 0) { 190 return null; 191 } 192 byte[] octets = new byte[length]; 193 payload.get(octets); 194 return new String(octets, charset); 195 } 196 } 197