1 package com.android.server.wifi.hotspot2.anqp; 2 3 import com.android.internal.annotations.VisibleForTesting; 4 5 import java.net.ProtocolException; 6 import java.nio.ByteBuffer; 7 import java.util.HashSet; 8 import java.util.Set; 9 10 /** 11 * The IP Address Type availability ANQP Element, IEEE802.11-2012 section 8.4.4.9 12 * 13 * Format: 14 * 15 * | IP Address | 16 * 1 17 * b0 b7 18 * | IPv6 Address | IPv4 Address | 19 * 2 bits 6 bits 20 * 21 * IPv4 Address field values: 22 * 0 - Address type not available 23 * 1 - Public IPv4 address available 24 * 2 - Port-restricted IPv4 address available 25 * 3 - Single NATed private IPv4 address available 26 * 4 - Single NATed private IPv4 address available 27 * 5 - Port-restricted IPv4 address and single NATed IPv4 address available 28 * 6 - Port-restricted IPv4 address and double NATed IPv4 address available 29 * 7 - Availability of the address type is not known 30 * 31 * IPv6 Address field values: 32 * 0 - Address type not available 33 * 1 - Address type not available 34 * 2 - Availability of the address type not known 35 * 36 */ 37 public class IPAddressTypeAvailabilityElement extends ANQPElement { 38 @VisibleForTesting 39 public static final int EXPECTED_BUFFER_LENGTH = 1; 40 41 /** 42 * Constants for IPv4 availability. 43 */ 44 public static final int IPV4_NOT_AVAILABLE = 0; 45 public static final int IPV4_PUBLIC = 1; 46 public static final int IPV4_PORT_RESTRICTED = 2; 47 public static final int IPV4_SINGLE_NAT = 3; 48 public static final int IPV4_DOUBLE_NAT = 4; 49 public static final int IPV4_PORT_RESTRICTED_AND_SINGLE_NAT = 5; 50 public static final int IPV4_PORT_RESTRICTED_AND_DOUBLE_NAT = 6; 51 public static final int IPV4_UNKNOWN = 7; 52 private static final Set<Integer> IPV4_AVAILABILITY = new HashSet<Integer>(); 53 static { 54 IPV4_AVAILABILITY.add(IPV4_NOT_AVAILABLE); 55 IPV4_AVAILABILITY.add(IPV4_PUBLIC); 56 IPV4_AVAILABILITY.add(IPV4_PORT_RESTRICTED); 57 IPV4_AVAILABILITY.add(IPV4_SINGLE_NAT); 58 IPV4_AVAILABILITY.add(IPV4_DOUBLE_NAT); 59 IPV4_AVAILABILITY.add(IPV4_PORT_RESTRICTED_AND_SINGLE_NAT); 60 IPV4_AVAILABILITY.add(IPV4_PORT_RESTRICTED_AND_DOUBLE_NAT); 61 } 62 63 /** 64 * Constants for IPv6 availability. 65 */ 66 public static final int IPV6_NOT_AVAILABLE = 0; 67 public static final int IPV6_AVAILABLE = 1; 68 public static final int IPV6_UNKNOWN = 2; 69 private static final Set<Integer> IPV6_AVAILABILITY = new HashSet<Integer>(); 70 static { 71 IPV6_AVAILABILITY.add(IPV6_NOT_AVAILABLE); 72 IPV6_AVAILABILITY.add(IPV6_AVAILABLE); 73 IPV6_AVAILABILITY.add(IPV6_UNKNOWN); 74 } 75 76 private static final int IPV4_AVAILABILITY_MASK = 0x3F; 77 private static final int IPV6_AVAILABILITY_MASK = 0x3; 78 79 private final int mV4Availability; 80 private final int mV6Availability; 81 82 @VisibleForTesting IPAddressTypeAvailabilityElement(int v4Availability, int v6Availability)83 public IPAddressTypeAvailabilityElement(int v4Availability, int v6Availability) { 84 super(Constants.ANQPElementType.ANQPIPAddrAvailability); 85 mV4Availability = v4Availability; 86 mV6Availability = v6Availability; 87 } 88 89 /** 90 * Parse an IPAddressTypeAvailabilityElement from the given buffer. 91 * 92 * @param payload The byte buffer to read from 93 * @return {@link IPAddressTypeAvailabilityElement} 94 * @throws ProtocolException 95 */ parse(ByteBuffer payload)96 public static IPAddressTypeAvailabilityElement parse(ByteBuffer payload) 97 throws ProtocolException { 98 if (payload.remaining() != EXPECTED_BUFFER_LENGTH) { 99 throw new ProtocolException("Unexpected buffer length: " + payload.remaining()); 100 } 101 102 int ipField = payload.get() & 0xFF; 103 104 int v6Availability = ipField & IPV6_AVAILABILITY_MASK; 105 if (!IPV6_AVAILABILITY.contains(v6Availability)) { 106 v6Availability = IPV6_UNKNOWN; 107 } 108 109 int v4Availability = (ipField >> 2) & IPV4_AVAILABILITY_MASK; 110 if (!IPV4_AVAILABILITY.contains(v4Availability)) { 111 v4Availability = IPV4_UNKNOWN; 112 } 113 114 return new IPAddressTypeAvailabilityElement(v4Availability, v6Availability); 115 } 116 getV4Availability()117 public int getV4Availability() { 118 return mV4Availability; 119 } 120 getV6Availability()121 public int getV6Availability() { 122 return mV6Availability; 123 } 124 125 @Override equals(Object thatObject)126 public boolean equals(Object thatObject) { 127 if (this == thatObject) { 128 return true; 129 } 130 if (!(thatObject instanceof IPAddressTypeAvailabilityElement)) { 131 return false; 132 } 133 IPAddressTypeAvailabilityElement that = (IPAddressTypeAvailabilityElement) thatObject; 134 return mV4Availability == that.mV4Availability && mV6Availability == that.mV6Availability; 135 } 136 137 @Override hashCode()138 public int hashCode() { 139 return mV4Availability << 2 + mV6Availability; 140 } 141 142 @Override toString()143 public String toString() { 144 return "IPAddressTypeAvailability{" + 145 "mV4Availability=" + mV4Availability + 146 ", mV6Availability=" + mV6Availability + 147 '}'; 148 } 149 } 150