Skip to content
Snippets Groups Projects
Commit 1c363601 authored by Yan Yan's avatar Yan Yan
Browse files

[XFRM_MSG_GETSA] Support xfrm_address_t and xfrm_usersa_id

Add xfrm_address_t and xfrm_usersa_id structs

Bug: 308011229
Test: atest NetworkStaticLibTests:com.android.net.moduletests.util.netlink
      (new tests added)
Change-Id: I552983d7e768e7fb8ba307ffc55060c8b35e7436
parent 65186a72
No related branches found
No related tags found
No related merge requests found
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.net.module.util.netlink;
import android.system.OsConstants;
import androidx.annotation.NonNull;
import com.android.net.module.util.Struct;
import com.android.net.module.util.Struct.Field;
import com.android.net.module.util.Struct.Type;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* Struct xfrm_address_t
*
* <p>see include/uapi/linux/xfrm.h
*
* <pre>
* typedef union {
* __be32 a4;
* __be32 a6[4];
* struct in6_addr in6;
* } xfrm_address_t;
* </pre>
*
* @hide
*/
public class IpSecStructXfrmAddressT extends Struct {
private static final int IPV4_ADDRESS_LEN = 4;
public static final int STRUCT_SIZE = 16;
@Field(order = 0, type = Type.ByteArray, arraysize = STRUCT_SIZE)
public final byte[] address;
// Constructor that allows Strutc.parse(Class<T>, ByteBuffer) to work
public IpSecStructXfrmAddressT(@NonNull byte[] address) {
this.address = address.clone();
}
// Constructor to build a new message
public IpSecStructXfrmAddressT(@NonNull InetAddress inetAddress) {
this.address = new byte[STRUCT_SIZE];
final byte[] addressBytes = inetAddress.getAddress();
System.arraycopy(addressBytes, 0, address, 0, addressBytes.length);
}
/** Return the address in InetAddress */
public InetAddress getAddress(int family) {
final byte[] addressBytes;
if (family == OsConstants.AF_INET6) {
addressBytes = this.address;
} else if (family == OsConstants.AF_INET) {
addressBytes = new byte[IPV4_ADDRESS_LEN];
System.arraycopy(this.address, 0, addressBytes, 0, addressBytes.length);
} else {
throw new IllegalArgumentException("Invalid IP family " + family);
}
try {
return InetAddress.getByAddress(addressBytes);
} catch (UnknownHostException e) {
// This should never happen
throw new IllegalArgumentException(
"Illegal length of IP address " + addressBytes.length, e);
}
}
}
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.net.module.util.netlink;
import androidx.annotation.NonNull;
import com.android.net.module.util.Struct;
import com.android.net.module.util.Struct.Field;
import com.android.net.module.util.Struct.Type;
import java.net.InetAddress;
/**
* Struct xfrm_usersa_id
*
* <p>see include/uapi/linux/xfrm.h
*
* <pre>
* struct xfrm_usersa_id {
* xfrm_address_t daddr;
* __be32 spi;
* __u16 family;
* __u8 proto;
* };
* </pre>
*
* @hide
*/
public class IpSecStructXfrmUsersaId extends Struct {
public static final int STRUCT_SIZE = 24;
@Field(order = 0, type = Type.ByteArray, arraysize = 16)
public final byte[] nestedStructDAddr; // xfrm_address_t
@Field(order = 1, type = Type.UBE32)
public final long spi;
@Field(order = 2, type = Type.U16)
public final int family;
@Field(order = 3, type = Type.U8, padding = 1)
public final short proto;
@Computed private final IpSecStructXfrmAddressT mDestXfrmAddressT;
// Constructor that allows Strutc.parse(Class<T>, ByteBuffer) to work
public IpSecStructXfrmUsersaId(
@NonNull byte[] nestedStructDAddr, long spi, int family, short proto) {
this.nestedStructDAddr = nestedStructDAddr.clone();
this.spi = spi;
this.family = family;
this.proto = proto;
mDestXfrmAddressT = new IpSecStructXfrmAddressT(this.nestedStructDAddr);
}
// Constructor to build a new message
public IpSecStructXfrmUsersaId(
@NonNull InetAddress destAddress, long spi, int family, short proto) {
this(new IpSecStructXfrmAddressT(destAddress).writeToBytes(), spi, family, proto);
}
/** Return the destination address */
public InetAddress getDestAddress() {
return mDestXfrmAddressT.getAddress(family);
}
}
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.net.module.util.netlink;
import androidx.annotation.NonNull;
/** Base calss for XFRM netlink messages */
// Developer notes: The Linux kernel includes a number of XFRM structs that are not standard netlink
// attributes (e.g., xfrm_usersa_id). These structs are unlikely to change size, so this XFRM
// netlink message implementation assumes their sizes will remain stable. If any non-attribute
// struct size changes, it should be caught by CTS and then developers should add
// kernel-version-based behvaiours.
public abstract class IpSecXfrmNetlinkMessage extends NetlinkMessage {
// TODO: STOPSHIP: b/308011229 Remove it when OsConstants.IPPROTO_ESP is exposed
public static final int IPPROTO_ESP = 50;
public IpSecXfrmNetlinkMessage(@NonNull StructNlMsgHdr header) {
super(header);
}
// TODO: Add the support for parsing messages
}
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.net.module.util.netlink;
import static com.android.net.module.util.netlink.IpSecXfrmNetlinkMessage.IPPROTO_ESP;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import android.net.InetAddresses;
import android.system.OsConstants;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.net.module.util.HexDump;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpSecStructXfrmUsersaIdTest {
private static final String EXPECTED_HEX_STRING =
"C0000201000000000000000000000000" + "7768440002003200";
private static final byte[] EXPECTED_HEX = HexDump.hexStringToByteArray(EXPECTED_HEX_STRING);
private static final InetAddress DEST_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1");
private static final long SPI = 0x77684400;
private static final int FAMILY = OsConstants.AF_INET;
private static final short PROTO = IPPROTO_ESP;
@Test
public void testEncode() throws Exception {
final IpSecStructXfrmUsersaId struct =
new IpSecStructXfrmUsersaId(DEST_ADDRESS, SPI, FAMILY, PROTO);
ByteBuffer buffer = ByteBuffer.allocate(EXPECTED_HEX.length);
buffer.order(ByteOrder.nativeOrder());
struct.writeToByteBuffer(buffer);
assertArrayEquals(EXPECTED_HEX, buffer.array());
}
@Test
public void testDecode() throws Exception {
final ByteBuffer buffer = ByteBuffer.wrap(EXPECTED_HEX);
buffer.order(ByteOrder.nativeOrder());
final IpSecStructXfrmUsersaId struct =
IpSecStructXfrmUsersaId.parse(IpSecStructXfrmUsersaId.class, buffer);
assertEquals(DEST_ADDRESS, struct.getDestAddress());
assertEquals(SPI, struct.spi);
assertEquals(FAMILY, struct.family);
assertEquals(PROTO, struct.proto);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment