1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.metrics;
18 
19 import android.annotation.SystemApi;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.util.SparseArray;
23 
24 import com.android.internal.util.MessageUtils;
25 
26 /**
27  * {@hide} Event class used to record error events when parsing DHCP response packets.
28  */
29 @SystemApi
30 public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcelable {
31     public static final int L2_ERROR   = 1;
32     public static final int L3_ERROR   = 2;
33     public static final int L4_ERROR   = 3;
34     public static final int DHCP_ERROR = 4;
35     public static final int MISC_ERROR = 5;
36 
37     public static final int L2_TOO_SHORT               = makeErrorCode(L2_ERROR, 1);
38     public static final int L2_WRONG_ETH_TYPE          = makeErrorCode(L2_ERROR, 2);
39 
40     public static final int L3_TOO_SHORT               = makeErrorCode(L3_ERROR, 1);
41     public static final int L3_NOT_IPV4                = makeErrorCode(L3_ERROR, 2);
42     public static final int L3_INVALID_IP              = makeErrorCode(L3_ERROR, 3);
43 
44     public static final int L4_NOT_UDP                 = makeErrorCode(L4_ERROR, 1);
45     public static final int L4_WRONG_PORT              = makeErrorCode(L4_ERROR, 2);
46 
47     public static final int BOOTP_TOO_SHORT            = makeErrorCode(DHCP_ERROR, 1);
48     public static final int DHCP_BAD_MAGIC_COOKIE      = makeErrorCode(DHCP_ERROR, 2);
49     public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3);
50     public static final int DHCP_NO_MSG_TYPE           = makeErrorCode(DHCP_ERROR, 4);
51     public static final int DHCP_UNKNOWN_MSG_TYPE      = makeErrorCode(DHCP_ERROR, 5);
52 
53     public static final int BUFFER_UNDERFLOW           = makeErrorCode(MISC_ERROR, 1);
54     public static final int RECEIVE_ERROR              = makeErrorCode(MISC_ERROR, 2);
55 
56     public final String ifName;
57     // error code byte format (MSB to LSB):
58     // byte 0: error type
59     // byte 1: error subtype
60     // byte 2: unused
61     // byte 3: optional code
62     public final int errorCode;
63 
DhcpErrorEvent(String ifName, int errorCode)64     private DhcpErrorEvent(String ifName, int errorCode) {
65         this.ifName = ifName;
66         this.errorCode = errorCode;
67     }
68 
DhcpErrorEvent(Parcel in)69     private DhcpErrorEvent(Parcel in) {
70         this.ifName = in.readString();
71         this.errorCode = in.readInt();
72     }
73 
writeToParcel(Parcel out, int flags)74     public void writeToParcel(Parcel out, int flags) {
75         out.writeString(ifName);
76         out.writeInt(errorCode);
77     }
78 
describeContents()79     public int describeContents() {
80         return 0;
81     }
82 
83     public static final Parcelable.Creator<DhcpErrorEvent> CREATOR
84         = new Parcelable.Creator<DhcpErrorEvent>() {
85         public DhcpErrorEvent createFromParcel(Parcel in) {
86             return new DhcpErrorEvent(in);
87         }
88 
89         public DhcpErrorEvent[] newArray(int size) {
90             return new DhcpErrorEvent[size];
91         }
92     };
93 
logParseError(String ifName, int errorCode)94     public static void logParseError(String ifName, int errorCode) {
95         logEvent(new DhcpErrorEvent(ifName, errorCode));
96     }
97 
logReceiveError(String ifName)98     public static void logReceiveError(String ifName) {
99         logEvent(new DhcpErrorEvent(ifName, RECEIVE_ERROR));
100     }
101 
errorCodeWithOption(int errorCode, int option)102     public static int errorCodeWithOption(int errorCode, int option) {
103         return (0xFFFF0000 & errorCode) | (0xFF & option);
104     }
105 
makeErrorCode(int type, int subtype)106     private static int makeErrorCode(int type, int subtype) {
107         return (type << 24) | ((0xFF & subtype) << 16);
108     }
109 
110     @Override
toString()111     public String toString() {
112         return String.format("DhcpErrorEvent(%s, %s)", ifName, Decoder.constants.get(errorCode));
113     }
114 
115     final static class Decoder {
116         static final SparseArray<String> constants =
117                 MessageUtils.findMessageNames(new Class[]{DhcpErrorEvent.class},
118                 new String[]{"L2_", "L3_", "L4_", "BOOTP_", "DHCP_", "BUFFER_", "RECEIVE_"});
119     }
120 }
121