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