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