blob: bdb246f516a27c073a72bbd4aa9ab09bd5de97fb [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;
24import android.system.OsConstants;
25
26import java.net.Inet4Address;
27import java.net.InetAddress;
28import java.nio.ByteBuffer;
29import java.nio.ByteOrder;
30
31/** @hide */
32public final class NattKeepalivePacketData extends KeepalivePacketData {
33
34 // This should only be constructed via static factory methods, such as
35 // nattKeepalivePacket
36 private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
37 InetAddress dstAddress, int dstPort, byte[] data) throws
38 InvalidPacketException {
39 super(srcAddress, srcPort, dstAddress, dstPort, data);
40 }
41
42 /**
43 * Factory method to create Nat-T keepalive packet structure.
44 */
45 public static NattKeepalivePacketData nattKeepalivePacket(
46 InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
47 throws InvalidPacketException {
48
49 if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) {
markchien150e1912018-12-27 22:49:51 +080050 throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
junyulai06835112019-01-03 18:50:15 +080051 }
52
53 if (dstPort != NattSocketKeepalive.NATT_PORT) {
markchien150e1912018-12-27 22:49:51 +080054 throw new InvalidPacketException(ERROR_INVALID_PORT);
junyulai06835112019-01-03 18:50:15 +080055 }
56
57 int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1;
58 ByteBuffer buf = ByteBuffer.allocate(length);
59 buf.order(ByteOrder.BIG_ENDIAN);
60 buf.putShort((short) 0x4500); // IP version and TOS
61 buf.putShort((short) length);
62 buf.putInt(0); // ID, flags, offset
63 buf.put((byte) 64); // TTL
64 buf.put((byte) OsConstants.IPPROTO_UDP);
65 int ipChecksumOffset = buf.position();
66 buf.putShort((short) 0); // IP checksum
67 buf.put(srcAddress.getAddress());
68 buf.put(dstAddress.getAddress());
69 buf.putShort((short) srcPort);
70 buf.putShort((short) dstPort);
71 buf.putShort((short) (length - 20)); // UDP length
72 int udpChecksumOffset = buf.position();
73 buf.putShort((short) 0); // UDP checksum
74 buf.put((byte) 0xff); // NAT-T keepalive
75 buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0));
76 buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH));
77
78 return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array());
79 }
80}