1 /*
2  * Copyright (C) 2020 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 package android.net;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.annotation.SystemApi;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 import java.net.InetAddress;
25 import java.util.Objects;
26 
27 /**
28  * Represents the actual tcp keep alive packets which will be used for hardware offload.
29  * @hide
30  */
31 @SystemApi
32 public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
33     private static final String TAG = "TcpKeepalivePacketData";
34 
35     /**
36      * TCP sequence number.
37      * @hide
38      */
39     public final int tcpSeq;
40 
41     /**
42      * TCP ACK number.
43      * @hide
44      */
45     public final int tcpAck;
46 
47     /**
48      * TCP RCV window.
49      * @hide
50      */
51     public final int tcpWindow;
52 
53     /** TCP RCV window scale.
54      * @hide
55      */
56     public final int tcpWindowScale;
57 
58     /**
59      * IP TOS.
60      * @hide
61      */
62     public final int ipTos;
63 
64     /**
65      * IP TTL.
66      * @hide
67      */
68     public final int ipTtl;
69 
70     public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort,
71             @NonNull final InetAddress dstAddress, int dstPort, @NonNull final byte[] data,
72             int tcpSeq, int tcpAck, int tcpWindow, int tcpWindowScale, int ipTos, int ipTtl)
73             throws InvalidPacketException {
74         super(srcAddress, srcPort, dstAddress, dstPort, data);
75         this.tcpSeq = tcpSeq;
76         this.tcpAck = tcpAck;
77         this.tcpWindow = tcpWindow;
78         this.tcpWindowScale = tcpWindowScale;
79         this.ipTos = ipTos;
80         this.ipTtl = ipTtl;
81     }
82 
83     /**
84      * Get the TCP sequence number.
85      *
86      * See https://tools.ietf.org/html/rfc793#page-15.
87      */
88     public int getTcpSeq() {
89         return tcpSeq;
90     }
91 
92     /**
93      * Get the TCP ACK number.
94      *
95      * See https://tools.ietf.org/html/rfc793#page-15.
96      */
97     public int getTcpAck() {
98         return tcpAck;
99     }
100 
101     /**
102      * Get the TCP RCV window.
103      *
104      * See https://tools.ietf.org/html/rfc793#page-15.
105      */
106     public int getTcpWindow() {
107         return tcpWindow;
108     }
109 
110     /**
111      * Get the TCP RCV window scale.
112      *
113      * See https://tools.ietf.org/html/rfc793#page-15.
114      */
115     public int getTcpWindowScale() {
116         return tcpWindowScale;
117     }
118 
119     /**
120      * Get the IP type of service.
121      */
122     public int getIpTos() {
123         return ipTos;
124     }
125 
126     /**
127      * Get the IP TTL.
128      */
129     public int getIpTtl() {
130         return ipTtl;
131     }
132 
133     @Override
134     public boolean equals(@Nullable final Object o) {
135         if (!(o instanceof TcpKeepalivePacketData)) return false;
136         final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o;
137         final InetAddress srcAddress = getSrcAddress();
138         final InetAddress dstAddress = getDstAddress();
139         return srcAddress.equals(other.getSrcAddress())
140                 && dstAddress.equals(other.getDstAddress())
141                 && getSrcPort() == other.getSrcPort()
142                 && getDstPort() == other.getDstPort()
143                 && this.tcpAck == other.tcpAck
144                 && this.tcpSeq == other.tcpSeq
145                 && this.tcpWindow == other.tcpWindow
146                 && this.tcpWindowScale == other.tcpWindowScale
147                 && this.ipTos == other.ipTos
148                 && this.ipTtl == other.ipTtl;
149     }
150 
151     @Override
152     public int hashCode() {
153         return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(),
154                 tcpAck, tcpSeq, tcpWindow, tcpWindowScale, ipTos, ipTtl);
155     }
156 
157     /**
158      * Parcelable Implementation.
159      * Note that this object implements parcelable (and needs to keep doing this as it inherits
160      * from a class that does), but should usually be parceled as a stable parcelable using
161      * the toStableParcelable() and fromStableParcelable() methods.
162      */
163     @Override
164     public int describeContents() {
165         return 0;
166     }
167 
168     /** Write to parcel. */
169     @Override
170     public void writeToParcel(@NonNull Parcel out, int flags) {
171         out.writeString(getSrcAddress().getHostAddress());
172         out.writeString(getDstAddress().getHostAddress());
173         out.writeInt(getSrcPort());
174         out.writeInt(getDstPort());
175         out.writeByteArray(getPacket());
176         out.writeInt(tcpSeq);
177         out.writeInt(tcpAck);
178         out.writeInt(tcpWindow);
179         out.writeInt(tcpWindowScale);
180         out.writeInt(ipTos);
181         out.writeInt(ipTtl);
182     }
183 
184     private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException {
185         InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString());
186         InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString());
187         int srcPort = in.readInt();
188         int dstPort = in.readInt();
189         byte[] packet = in.createByteArray();
190         int tcpSeq = in.readInt();
191         int tcpAck = in.readInt();
192         int tcpWnd = in.readInt();
193         int tcpWndScale = in.readInt();
194         int ipTos = in.readInt();
195         int ipTtl = in.readInt();
196         return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq,
197                 tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl);
198     }
199 
200     /** Parcelable Creator. */
201     public static final @NonNull Parcelable.Creator<TcpKeepalivePacketData> CREATOR =
202             new Parcelable.Creator<TcpKeepalivePacketData>() {
203                 public TcpKeepalivePacketData createFromParcel(Parcel in) {
204                     try {
205                         return readFromParcel(in);
206                     } catch (InvalidPacketException e) {
207                         throw new IllegalArgumentException(
208                                 "Invalid TCP keepalive data: " + e.getError());
209                     }
210                 }
211 
212                 public TcpKeepalivePacketData[] newArray(int size) {
213                     return new TcpKeepalivePacketData[size];
214                 }
215             };
216 
217     @Override
218     public String toString() {
219         return "saddr: " + getSrcAddress()
220                 + " daddr: " + getDstAddress()
221                 + " sport: " + getSrcPort()
222                 + " dport: " + getDstPort()
223                 + " seq: " + tcpSeq
224                 + " ack: " + tcpAck
225                 + " window: " + tcpWindow
226                 + " windowScale: " + tcpWindowScale
227                 + " tos: " + ipTos
228                 + " ttl: " + ipTtl;
229     }
230 }
231