blob: 06838fe655b76182e1a67ae56167a2113d6d0824 [file] [log] [blame]
junyulai3a5caf82019-01-03 18:50:15 +08001/*
2 * Copyright (C) 2018 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
markchien46f41d42018-12-27 22:49:51 +080019import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
20import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
21
Aaron Huang9deb7632019-04-23 22:17:16 +080022import android.annotation.NonNull;
junyulai3a5caf82019-01-03 18:50:15 +080023import android.net.SocketKeepalive.InvalidPacketException;
24import android.net.util.IpUtils;
Aaron Huang9deb7632019-04-23 22:17:16 +080025import android.os.Parcelable;
junyulai3a5caf82019-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 Huang9deb7632019-04-23 22:17:16 +080034public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
junyulai3a5caf82019-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)) {
markchien46f41d42018-12-27 22:49:51 +080051 throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
junyulai3a5caf82019-01-03 18:50:15 +080052 }
53
54 if (dstPort != NattSocketKeepalive.NATT_PORT) {
markchien46f41d42018-12-27 22:49:51 +080055 throw new InvalidPacketException(ERROR_INVALID_PORT);
junyulai3a5caf82019-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 Huang9deb7632019-04-23 22:17:16 +080081
82 /**
83 * Convert this NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
84 */
85 @NonNull
86 public NattKeepalivePacketDataParcelable toStableParcelable() {
87 final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
88
89 parcel.srcAddress = srcAddress.getAddress();
90 parcel.srcPort = srcPort;
91 parcel.dstAddress = dstAddress.getAddress();
92 parcel.dstPort = dstPort;
93 return parcel;
94 }
junyulai3a5caf82019-01-03 18:50:15 +080095}