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.StructNlMsgHdr.NLM_F_REQUEST;
20 import static com.android.net.module.util.netlink.xfrm.XfrmNetlinkMessage.XFRM_MSG_GETSA;
21 
22 import android.system.OsConstants;
23 
24 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable;
26 
27 import com.android.net.module.util.Struct;
28 import com.android.net.module.util.netlink.StructNlMsgHdr;
29 
30 import java.net.Inet4Address;
31 import java.net.InetAddress;
32 import java.nio.ByteBuffer;
33 
34 /**
35  * An XfrmNetlinkMessage subclass for XFRM_MSG_GETSA messages.
36  *
37  * <p>see include/uapi/linux/xfrm.h
38  *
39  * <p>XFRM_MSG_GETSA syntax
40  *
41  * <ul>
42  *   <li>TLV: xfrm_usersa_id
43  *   <li>Optional Attributes: XFRMA_MARK, XFRMA_SRCADDR
44  * </ul>
45  *
46  * @hide
47  */
48 public class XfrmNetlinkGetSaMessage extends XfrmNetlinkMessage {
49     @NonNull private final StructXfrmUsersaId mXfrmUsersaId;
50 
XfrmNetlinkGetSaMessage( @onNull final StructNlMsgHdr header, @NonNull final StructXfrmUsersaId xfrmUsersaId)51     private XfrmNetlinkGetSaMessage(
52             @NonNull final StructNlMsgHdr header, @NonNull final StructXfrmUsersaId xfrmUsersaId) {
53         super(header);
54         mXfrmUsersaId = xfrmUsersaId;
55     }
56 
XfrmNetlinkGetSaMessage( @onNull final StructNlMsgHdr header, @NonNull final InetAddress destAddress, long spi, short proto)57     private XfrmNetlinkGetSaMessage(
58             @NonNull final StructNlMsgHdr header,
59             @NonNull final InetAddress destAddress,
60             long spi,
61             short proto) {
62         super(header);
63 
64         final int family =
65                 destAddress instanceof Inet4Address ? OsConstants.AF_INET : OsConstants.AF_INET6;
66         mXfrmUsersaId = new StructXfrmUsersaId(destAddress, spi, family, proto);
67     }
68 
69     @Override
packPayload(@onNull final ByteBuffer byteBuffer)70     protected void packPayload(@NonNull final ByteBuffer byteBuffer) {
71         mXfrmUsersaId.writeToByteBuffer(byteBuffer);
72     }
73 
74     /**
75      * Parse XFRM_MSG_GETSA message from ByteBuffer.
76      *
77      * <p>This method should be called from NetlinkMessage#parse(ByteBuffer, int) for generic
78      * message validation and processing
79      *
80      * @param nlmsghdr netlink message header.
81      * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes. MUST be
82      *                   host order
83      */
84     @Nullable
parseInternal( @onNull final StructNlMsgHdr nlmsghdr, @NonNull final ByteBuffer byteBuffer)85     static XfrmNetlinkGetSaMessage parseInternal(
86             @NonNull final StructNlMsgHdr nlmsghdr, @NonNull final ByteBuffer byteBuffer) {
87         final StructXfrmUsersaId xfrmUsersaId = Struct.parse(StructXfrmUsersaId.class, byteBuffer);
88         if (xfrmUsersaId == null) {
89             return null;
90         }
91 
92         // Attributes not supported. Don't bother handling them.
93 
94         return new XfrmNetlinkGetSaMessage(nlmsghdr, xfrmUsersaId);
95     }
96 
97     /** A convenient method to create a XFRM_MSG_GETSA message. */
newXfrmNetlinkGetSaMessage( @onNull final InetAddress destAddress, long spi, short proto)98     public static byte[] newXfrmNetlinkGetSaMessage(
99             @NonNull final InetAddress destAddress, long spi, short proto) {
100         final int payloadLen = StructXfrmUsersaId.STRUCT_SIZE;
101 
102         final StructNlMsgHdr nlmsghdr =
103                 new StructNlMsgHdr(payloadLen, XFRM_MSG_GETSA, NLM_F_REQUEST, 0);
104         final XfrmNetlinkGetSaMessage message =
105                 new XfrmNetlinkGetSaMessage(nlmsghdr, destAddress, spi, proto);
106 
107         final ByteBuffer byteBuffer = newNlMsgByteBuffer(payloadLen);
108         message.pack(byteBuffer);
109 
110         return byteBuffer.array();
111     }
112 
getStructXfrmUsersaId()113     public StructXfrmUsersaId getStructXfrmUsersaId() {
114         return mXfrmUsersaId;
115     }
116 }
117