1 /* 2 * Copyright (C) 2023 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 17 package com.android.net.module.util.netlink.xfrm; 18 19 import static com.android.net.module.util.netlink.xfrm.XfrmNetlinkMessage.XFRMA_REPLAY_ESN_VAL; 20 21 import android.util.Log; 22 23 import androidx.annotation.NonNull; 24 import androidx.annotation.Nullable; 25 26 import com.android.net.module.util.Struct; 27 import com.android.net.module.util.netlink.StructNlAttr; 28 import com.android.net.module.util.netlink.StructNlMsgHdr; 29 30 import java.nio.ByteBuffer; 31 import java.nio.ByteOrder; 32 33 /** 34 * A NetlinkMessage subclass for XFRM_MSG_NEWSA messages. 35 * 36 * <p>see also: <linux_src>/include/uapi/linux/xfrm.h 37 * 38 * <p>XFRM_MSG_NEWSA syntax 39 * 40 * <ul> 41 * <li>TLV: xfrm_usersa_info 42 * <li>Attributes: XFRMA_ALG_CRYPT, XFRMA_ALG_AUTH, XFRMA_OUTPUT_MARK, XFRMA_IF_ID, 43 * XFRMA_REPLAY_ESN_VAL,XFRMA_REPLAY_VAL 44 * </ul> 45 * 46 * @hide 47 */ 48 public class XfrmNetlinkNewSaMessage extends XfrmNetlinkMessage { 49 private static final String TAG = XfrmNetlinkNewSaMessage.class.getSimpleName(); 50 @NonNull private final StructXfrmUsersaInfo mXfrmUsersaInfo; 51 52 @NonNull private final StructXfrmReplayStateEsn mXfrmReplayStateEsn; 53 XfrmNetlinkNewSaMessage( @onNull final StructNlMsgHdr header, @NonNull final StructXfrmUsersaInfo xfrmUsersaInfo, @NonNull final StructXfrmReplayStateEsn xfrmReplayStateEsn)54 private XfrmNetlinkNewSaMessage( 55 @NonNull final StructNlMsgHdr header, 56 @NonNull final StructXfrmUsersaInfo xfrmUsersaInfo, 57 @NonNull final StructXfrmReplayStateEsn xfrmReplayStateEsn) { 58 super(header); 59 mXfrmUsersaInfo = xfrmUsersaInfo; 60 mXfrmReplayStateEsn = xfrmReplayStateEsn; 61 } 62 63 @Override packPayload(@onNull final ByteBuffer byteBuffer)64 protected void packPayload(@NonNull final ByteBuffer byteBuffer) { 65 mXfrmUsersaInfo.writeToByteBuffer(byteBuffer); 66 if (mXfrmReplayStateEsn != null) { 67 mXfrmReplayStateEsn.writeToByteBuffer(byteBuffer); 68 } 69 } 70 71 /** 72 * Parse XFRM_MSG_NEWSA message from ByteBuffer. 73 * 74 * <p>This method should be called from NetlinkMessage#parse(ByteBuffer, int) for generic 75 * message validation and processing 76 * 77 * @param nlmsghdr netlink message header. 78 * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes. MUST be 79 * host order 80 */ 81 @Nullable parseInternal( @onNull final StructNlMsgHdr nlmsghdr, @NonNull final ByteBuffer byteBuffer)82 static XfrmNetlinkNewSaMessage parseInternal( 83 @NonNull final StructNlMsgHdr nlmsghdr, @NonNull final ByteBuffer byteBuffer) { 84 final StructXfrmUsersaInfo xfrmUsersaInfo = 85 Struct.parse(StructXfrmUsersaInfo.class, byteBuffer); 86 if (xfrmUsersaInfo == null) { 87 Log.d(TAG, "parse: fail to parse xfrmUsersaInfo"); 88 return null; 89 } 90 91 StructXfrmReplayStateEsn xfrmReplayStateEsn = null; 92 93 final int payloadLen = nlmsghdr.nlmsg_len - StructNlMsgHdr.STRUCT_SIZE; 94 int parsedLength = StructXfrmUsersaInfo.STRUCT_SIZE; 95 while (parsedLength < payloadLen) { 96 final StructNlAttr attr = StructNlAttr.parse(byteBuffer); 97 98 if (attr == null) { 99 Log.d(TAG, "parse: fail to parse netlink attributes"); 100 return null; 101 } 102 103 final ByteBuffer attrValueBuff = ByteBuffer.wrap(attr.nla_value); 104 attrValueBuff.order(ByteOrder.nativeOrder()); 105 106 if (attr.nla_type == XFRMA_REPLAY_ESN_VAL) { 107 xfrmReplayStateEsn = StructXfrmReplayStateEsn.parse(attrValueBuff); 108 } 109 110 parsedLength += attr.nla_len; 111 } 112 113 // TODO: Add the support of XFRMA_REPLAY_VAL 114 115 if (xfrmReplayStateEsn == null) { 116 Log.d(TAG, "parse: xfrmReplayStateEsn not found"); 117 return null; 118 } 119 120 final XfrmNetlinkNewSaMessage msg = 121 new XfrmNetlinkNewSaMessage(nlmsghdr, xfrmUsersaInfo, xfrmReplayStateEsn); 122 123 return msg; 124 } 125 126 /** Return the TX sequence number in unisgned long */ getTxSequenceNumber()127 public long getTxSequenceNumber() { 128 return mXfrmReplayStateEsn.getTxSequenceNumber(); 129 } 130 131 /** Return the RX sequence number in unisgned long */ getRxSequenceNumber()132 public long getRxSequenceNumber() { 133 return mXfrmReplayStateEsn.getRxSequenceNumber(); 134 } 135 136 /** Return the bitmap */ getBitmap()137 public byte[] getBitmap() { 138 return mXfrmReplayStateEsn.getBitmap(); 139 } 140 141 /** Return the packet count in unsigned long */ getPacketCount()142 public long getPacketCount() { 143 // It is safe because "packets" is a 64-bit value 144 return mXfrmUsersaInfo.getCurrentLifetime().packets.longValue(); 145 } 146 147 /** Return the byte count in unsigned long */ getByteCount()148 public long getByteCount() { 149 // It is safe because "bytes" is a 64-bit value 150 return mXfrmUsersaInfo.getCurrentLifetime().bytes.longValue(); 151 } 152 153 /** Return the xfrm_usersa_info */ getXfrmUsersaInfo()154 public StructXfrmUsersaInfo getXfrmUsersaInfo() { 155 return mXfrmUsersaInfo; 156 } 157 } 158