blob: a77c244d6b404cc5a358fe3d7b3ab32eadb9d3c9 [file] [log] [blame]
junyulai06835112019-01-03 18:50:15 +08001/*
2 * Copyright (C) 2019 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
17package android.net;
18
markchien150e1912018-12-27 22:49:51 +080019import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
20import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
21
junyulai06835112019-01-03 18:50:15 +080022import android.net.SocketKeepalive.InvalidPacketException;
23import android.net.util.IpUtils;
junyulai02abbfd2019-06-03 17:51:41 +080024import android.os.Parcel;
Aaron Huang76985bd2019-04-23 22:17:16 +080025import android.os.Parcelable;
junyulai06835112019-01-03 18:50:15 +080026import android.system.OsConstants;
27
28import java.net.Inet4Address;
29import java.net.InetAddress;
30import java.nio.ByteBuffer;
31import java.nio.ByteOrder;
32
33/** @hide */
Aaron Huang76985bd2019-04-23 22:17:16 +080034public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
junyulai06835112019-01-03 18:50:15 +080035 // This should only be constructed via static factory methods, such as
36 // nattKeepalivePacket
37 private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
38 InetAddress dstAddress, int dstPort, byte[] data) throws
39 InvalidPacketException {
40 super(srcAddress, srcPort, dstAddress, dstPort, data);
41 }
42
43 /**
44 * Factory method to create Nat-T keepalive packet structure.
45 */
46 public static NattKeepalivePacketData nattKeepalivePacket(
47 InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
48 throws InvalidPacketException {
49
50 if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) {
markchien150e1912018-12-27 22:49:51 +080051 throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
junyulai06835112019-01-03 18:50:15 +080052 }
53
54 if (dstPort != NattSocketKeepalive.NATT_PORT) {
markchien150e1912018-12-27 22:49:51 +080055 throw new InvalidPacketException(ERROR_INVALID_PORT);
junyulai06835112019-01-03 18:50:15 +080056 }
57
58 int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1;
59 ByteBuffer buf = ByteBuffer.allocate(length);
60 buf.order(ByteOrder.BIG_ENDIAN);
61 buf.putShort((short) 0x4500); // IP version and TOS
62 buf.putShort((short) length);
63 buf.putInt(0); // ID, flags, offset
64 buf.put((byte) 64); // TTL
65 buf.put((byte) OsConstants.IPPROTO_UDP);
66 int ipChecksumOffset = buf.position();
67 buf.putShort((short) 0); // IP checksum
68 buf.put(srcAddress.getAddress());
69 buf.put(dstAddress.getAddress());
70 buf.putShort((short) srcPort);
71 buf.putShort((short) dstPort);
72 buf.putShort((short) (length - 20)); // UDP length
73 int udpChecksumOffset = buf.position();
74 buf.putShort((short) 0); // UDP checksum
75 buf.put((byte) 0xff); // NAT-T keepalive
76 buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0));
77 buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH));
78
79 return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array());
80 }
Aaron Huang76985bd2019-04-23 22:17:16 +080081
junyulai02abbfd2019-06-03 17:51:41 +080082 /** Parcelable Implementation */
83 public int describeContents() {
84 return 0;
Aaron Huang76985bd2019-04-23 22:17:16 +080085 }
junyulai02abbfd2019-06-03 17:51:41 +080086
87 /** Write to parcel */
88 public void writeToParcel(Parcel out, int flags) {
89 out.writeString(srcAddress.getHostAddress());
90 out.writeString(dstAddress.getHostAddress());
91 out.writeInt(srcPort);
92 out.writeInt(dstPort);
93 }
94
95 /** Parcelable Creator */
96 public static final Parcelable.Creator<NattKeepalivePacketData> CREATOR =
97 new Parcelable.Creator<NattKeepalivePacketData>() {
98 public NattKeepalivePacketData createFromParcel(Parcel in) {
99 final InetAddress srcAddress =
100 InetAddresses.parseNumericAddress(in.readString());
101 final InetAddress dstAddress =
102 InetAddresses.parseNumericAddress(in.readString());
103 final int srcPort = in.readInt();
104 final int dstPort = in.readInt();
105 try {
106 return NattKeepalivePacketData.nattKeepalivePacket(srcAddress, srcPort,
107 dstAddress, dstPort);
108 } catch (InvalidPacketException e) {
109 throw new IllegalArgumentException(
110 "Invalid NAT-T keepalive data: " + e.error);
111 }
112 }
113
114 public NattKeepalivePacketData[] newArray(int size) {
115 return new NattKeepalivePacketData[size];
116 }
117 };
junyulai06835112019-01-03 18:50:15 +0800118}