Loading core/java/android/net/metrics/DhcpErrorEvent.java 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.metrics; import android.os.Parcel; import android.os.Parcelable; /** * {@hide} Event class used to record error events when parsing DHCP response packets. */ public class DhcpErrorEvent extends IpConnectivityEvent implements Parcelable { public static final String TAG = "DhcpErrorEvent"; public static final int L2_ERROR = 1; public static final int L3_ERROR = 2; public static final int L4_ERROR = 3; public static final int DHCP_ERROR = 4; public static final int MISC_ERROR = 5; public static final int L2_TOO_SHORT = makeErrorCode(L2_ERROR, 1); public static final int L2_WRONG_ETH_TYPE = makeErrorCode(L2_ERROR, 2); public static final int L3_TOO_SHORT = makeErrorCode(L3_ERROR, 1); public static final int L3_NOT_IPV4 = makeErrorCode(L3_ERROR, 2); public static final int L3_INVALID_IP = makeErrorCode(L3_ERROR, 3); public static final int L4_NOT_UDP = makeErrorCode(L4_ERROR, 1); public static final int L4_WRONG_PORT = makeErrorCode(L4_ERROR, 2); public static final int BOOTP_TOO_SHORT = makeErrorCode(DHCP_ERROR, 1); public static final int DHCP_BAD_MAGIC_COOKIE = makeErrorCode(DHCP_ERROR, 2); public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3); public static final int DHCP_NO_MSG_TYPE = makeErrorCode(DHCP_ERROR, 4); public static final int DHCP_UNKNOWN_MSG_TYPE = makeErrorCode(DHCP_ERROR, 5); public static final int BUFFER_UNDERFLOW = makeErrorCode(MISC_ERROR, 1); // error code byte format (MSB to LSB): // byte 0: error type // byte 1: error subtype // byte 2: unused // byte 3: optional code public final int errorCode; private DhcpErrorEvent(int errorCode) { this.errorCode = errorCode; } private DhcpErrorEvent(Parcel in) { this.errorCode = in.readInt(); } public void writeToParcel(Parcel out, int flags) { out.writeInt(errorCode); } public static final Parcelable.Creator<DhcpErrorEvent> CREATOR = new Parcelable.Creator<DhcpErrorEvent>() { public DhcpErrorEvent createFromParcel(Parcel in) { return new DhcpErrorEvent(in); } public DhcpErrorEvent[] newArray(int size) { return new DhcpErrorEvent[size]; } }; public static void logEvent(int errorCode) { IpConnectivityEvent.logEvent(IPCE_DHCP_PARSE_ERROR, new DhcpErrorEvent(errorCode)); } public static void logEvent(int errorCode, int option) { logEvent((0xFFFF0000 & errorCode) | (0xFF & option)); } private static int makeErrorCode(int type, int subtype) { return (type << 24) | ((0xFF & subtype) << 16); } } services/net/java/android/net/dhcp/DhcpPacket.java +18 −3 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package android.net.dhcp; import android.net.DhcpResults; import android.net.LinkAddress; import android.net.NetworkUtils; import android.net.metrics.DhcpErrorEvent; import android.os.Build; import android.os.SystemProperties; import android.system.OsConstants; Loading Loading @@ -765,6 +766,7 @@ abstract class DhcpPacket { // check to see if we need to parse L2, IP, and UDP encaps if (pktType == ENCAP_L2) { if (packet.remaining() < MIN_PACKET_LENGTH_L2) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L2_TOO_SHORT); throw new ParseException("L2 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L2); } Loading @@ -777,13 +779,16 @@ abstract class DhcpPacket { short l2type = packet.getShort(); if (l2type != OsConstants.ETH_P_IP) if (l2type != OsConstants.ETH_P_IP) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L2_WRONG_ETH_TYPE); throw new ParseException("Unexpected L2 type 0x%04x, expected 0x%04x", l2type, OsConstants.ETH_P_IP); } } if (pktType <= ENCAP_L3) { if (packet.remaining() < MIN_PACKET_LENGTH_L3) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_TOO_SHORT); throw new ParseException("L3 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L3); } Loading @@ -791,6 +796,7 @@ abstract class DhcpPacket { byte ipTypeAndLength = packet.get(); int ipVersion = (ipTypeAndLength & 0xf0) >> 4; if (ipVersion != 4) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_NOT_IPV4); throw new ParseException("Invalid IP version %d", ipVersion); } Loading @@ -808,6 +814,7 @@ abstract class DhcpPacket { ipDst = readIpAddress(packet); if (ipProto != IP_TYPE_UDP) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L4_NOT_UDP); throw new ParseException("Protocol not UDP: %d", ipProto); } Loading @@ -834,12 +841,14 @@ abstract class DhcpPacket { // socket to drop packets that don't have the right source ports. However, it's // possible that a packet arrives between when the socket is bound and when the // filter is set. http://b/26696823 . DhcpErrorEvent.logEvent(DhcpErrorEvent.L4_WRONG_PORT); throw new ParseException("Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort); } } // We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length. if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) { DhcpErrorEvent.logEvent(DhcpErrorEvent.BOOTP_TOO_SHORT); throw new ParseException("Invalid type or BOOTP packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_BOOTP); } Loading @@ -864,6 +873,7 @@ abstract class DhcpPacket { packet.get(ipv4addr); relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); } catch (UnknownHostException ex) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_INVALID_IP); throw new ParseException("Invalid IPv4 address: %s", Arrays.toString(ipv4addr)); } Loading @@ -888,6 +898,7 @@ abstract class DhcpPacket { int dhcpMagicCookie = packet.getInt(); if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) { DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE); throw new ParseException("Bad magic cookie 0x%08x, should be 0x%08x", dhcpMagicCookie, DHCP_MAGIC_COOKIE); } Loading @@ -896,9 +907,8 @@ abstract class DhcpPacket { boolean notFinishedOptions = true; while ((packet.position() < packet.limit()) && notFinishedOptions) { final byte optionType = packet.get(); // cannot underflow because position < limit try { byte optionType = packet.get(); if (optionType == DHCP_OPTION_END) { notFinishedOptions = false; } else if (optionType == DHCP_OPTION_PAD) { Loading Loading @@ -999,11 +1009,14 @@ abstract class DhcpPacket { } if (expectedLen != optionLen) { DhcpErrorEvent.logEvent( DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH, optionType); throw new ParseException("Invalid length %d for option %d, expected %d", optionLen, optionType, expectedLen); } } } catch (BufferUnderflowException e) { DhcpErrorEvent.logEvent(DhcpErrorEvent.BUFFER_UNDERFLOW, optionType); throw new ParseException("BufferUnderflowException"); } } Loading @@ -1012,6 +1025,7 @@ abstract class DhcpPacket { switch(dhcpType) { case (byte) 0xFF: DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_NO_MSG_TYPE); throw new ParseException("No DHCP message type option"); case DHCP_MESSAGE_TYPE_DISCOVER: newPacket = new DhcpDiscoverPacket( Loading Loading @@ -1045,6 +1059,7 @@ abstract class DhcpPacket { clientMac); break; default: DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_UNKNOWN_MSG_TYPE); throw new ParseException("Unimplemented DHCP type %d", dhcpType); } Loading Loading
core/java/android/net/metrics/DhcpErrorEvent.java 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.metrics; import android.os.Parcel; import android.os.Parcelable; /** * {@hide} Event class used to record error events when parsing DHCP response packets. */ public class DhcpErrorEvent extends IpConnectivityEvent implements Parcelable { public static final String TAG = "DhcpErrorEvent"; public static final int L2_ERROR = 1; public static final int L3_ERROR = 2; public static final int L4_ERROR = 3; public static final int DHCP_ERROR = 4; public static final int MISC_ERROR = 5; public static final int L2_TOO_SHORT = makeErrorCode(L2_ERROR, 1); public static final int L2_WRONG_ETH_TYPE = makeErrorCode(L2_ERROR, 2); public static final int L3_TOO_SHORT = makeErrorCode(L3_ERROR, 1); public static final int L3_NOT_IPV4 = makeErrorCode(L3_ERROR, 2); public static final int L3_INVALID_IP = makeErrorCode(L3_ERROR, 3); public static final int L4_NOT_UDP = makeErrorCode(L4_ERROR, 1); public static final int L4_WRONG_PORT = makeErrorCode(L4_ERROR, 2); public static final int BOOTP_TOO_SHORT = makeErrorCode(DHCP_ERROR, 1); public static final int DHCP_BAD_MAGIC_COOKIE = makeErrorCode(DHCP_ERROR, 2); public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3); public static final int DHCP_NO_MSG_TYPE = makeErrorCode(DHCP_ERROR, 4); public static final int DHCP_UNKNOWN_MSG_TYPE = makeErrorCode(DHCP_ERROR, 5); public static final int BUFFER_UNDERFLOW = makeErrorCode(MISC_ERROR, 1); // error code byte format (MSB to LSB): // byte 0: error type // byte 1: error subtype // byte 2: unused // byte 3: optional code public final int errorCode; private DhcpErrorEvent(int errorCode) { this.errorCode = errorCode; } private DhcpErrorEvent(Parcel in) { this.errorCode = in.readInt(); } public void writeToParcel(Parcel out, int flags) { out.writeInt(errorCode); } public static final Parcelable.Creator<DhcpErrorEvent> CREATOR = new Parcelable.Creator<DhcpErrorEvent>() { public DhcpErrorEvent createFromParcel(Parcel in) { return new DhcpErrorEvent(in); } public DhcpErrorEvent[] newArray(int size) { return new DhcpErrorEvent[size]; } }; public static void logEvent(int errorCode) { IpConnectivityEvent.logEvent(IPCE_DHCP_PARSE_ERROR, new DhcpErrorEvent(errorCode)); } public static void logEvent(int errorCode, int option) { logEvent((0xFFFF0000 & errorCode) | (0xFF & option)); } private static int makeErrorCode(int type, int subtype) { return (type << 24) | ((0xFF & subtype) << 16); } }
services/net/java/android/net/dhcp/DhcpPacket.java +18 −3 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ package android.net.dhcp; import android.net.DhcpResults; import android.net.LinkAddress; import android.net.NetworkUtils; import android.net.metrics.DhcpErrorEvent; import android.os.Build; import android.os.SystemProperties; import android.system.OsConstants; Loading Loading @@ -765,6 +766,7 @@ abstract class DhcpPacket { // check to see if we need to parse L2, IP, and UDP encaps if (pktType == ENCAP_L2) { if (packet.remaining() < MIN_PACKET_LENGTH_L2) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L2_TOO_SHORT); throw new ParseException("L2 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L2); } Loading @@ -777,13 +779,16 @@ abstract class DhcpPacket { short l2type = packet.getShort(); if (l2type != OsConstants.ETH_P_IP) if (l2type != OsConstants.ETH_P_IP) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L2_WRONG_ETH_TYPE); throw new ParseException("Unexpected L2 type 0x%04x, expected 0x%04x", l2type, OsConstants.ETH_P_IP); } } if (pktType <= ENCAP_L3) { if (packet.remaining() < MIN_PACKET_LENGTH_L3) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_TOO_SHORT); throw new ParseException("L3 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L3); } Loading @@ -791,6 +796,7 @@ abstract class DhcpPacket { byte ipTypeAndLength = packet.get(); int ipVersion = (ipTypeAndLength & 0xf0) >> 4; if (ipVersion != 4) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_NOT_IPV4); throw new ParseException("Invalid IP version %d", ipVersion); } Loading @@ -808,6 +814,7 @@ abstract class DhcpPacket { ipDst = readIpAddress(packet); if (ipProto != IP_TYPE_UDP) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L4_NOT_UDP); throw new ParseException("Protocol not UDP: %d", ipProto); } Loading @@ -834,12 +841,14 @@ abstract class DhcpPacket { // socket to drop packets that don't have the right source ports. However, it's // possible that a packet arrives between when the socket is bound and when the // filter is set. http://b/26696823 . DhcpErrorEvent.logEvent(DhcpErrorEvent.L4_WRONG_PORT); throw new ParseException("Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort); } } // We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length. if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) { DhcpErrorEvent.logEvent(DhcpErrorEvent.BOOTP_TOO_SHORT); throw new ParseException("Invalid type or BOOTP packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_BOOTP); } Loading @@ -864,6 +873,7 @@ abstract class DhcpPacket { packet.get(ipv4addr); relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); } catch (UnknownHostException ex) { DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_INVALID_IP); throw new ParseException("Invalid IPv4 address: %s", Arrays.toString(ipv4addr)); } Loading @@ -888,6 +898,7 @@ abstract class DhcpPacket { int dhcpMagicCookie = packet.getInt(); if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) { DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE); throw new ParseException("Bad magic cookie 0x%08x, should be 0x%08x", dhcpMagicCookie, DHCP_MAGIC_COOKIE); } Loading @@ -896,9 +907,8 @@ abstract class DhcpPacket { boolean notFinishedOptions = true; while ((packet.position() < packet.limit()) && notFinishedOptions) { final byte optionType = packet.get(); // cannot underflow because position < limit try { byte optionType = packet.get(); if (optionType == DHCP_OPTION_END) { notFinishedOptions = false; } else if (optionType == DHCP_OPTION_PAD) { Loading Loading @@ -999,11 +1009,14 @@ abstract class DhcpPacket { } if (expectedLen != optionLen) { DhcpErrorEvent.logEvent( DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH, optionType); throw new ParseException("Invalid length %d for option %d, expected %d", optionLen, optionType, expectedLen); } } } catch (BufferUnderflowException e) { DhcpErrorEvent.logEvent(DhcpErrorEvent.BUFFER_UNDERFLOW, optionType); throw new ParseException("BufferUnderflowException"); } } Loading @@ -1012,6 +1025,7 @@ abstract class DhcpPacket { switch(dhcpType) { case (byte) 0xFF: DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_NO_MSG_TYPE); throw new ParseException("No DHCP message type option"); case DHCP_MESSAGE_TYPE_DISCOVER: newPacket = new DhcpDiscoverPacket( Loading Loading @@ -1045,6 +1059,7 @@ abstract class DhcpPacket { clientMac); break; default: DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_UNKNOWN_MSG_TYPE); throw new ParseException("Unimplemented DHCP type %d", dhcpType); } Loading