• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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;
18 
19 import android.net.IpPrefix;
20 import android.system.OsConstants;
21 
22 import androidx.annotation.NonNull;
23 import androidx.annotation.Nullable;
24 import androidx.annotation.VisibleForTesting;
25 
26 import java.net.Inet6Address;
27 import java.nio.ByteBuffer;
28 
29 /**
30  * A NetlinkMessage subclass for rtnetlink address messages.
31  *
32  * RtNetlinkPrefixMessage.parse() must be called with a ByteBuffer that contains exactly one
33  * netlink message.
34  *
35  * see also:
36  *
37  *     include/uapi/linux/rtnetlink.h
38  *
39  * @hide
40  */
41 public class RtNetlinkPrefixMessage extends NetlinkMessage {
42     public static final short PREFIX_ADDRESS       = 1;
43     public static final short PREFIX_CACHEINFO     = 2;
44 
45     @NonNull
46     private StructPrefixMsg mPrefixmsg;
47     @NonNull
48     private IpPrefix mPrefix;
49     private long mPreferredLifetime;
50     private long mValidLifetime;
51 
52     @VisibleForTesting
RtNetlinkPrefixMessage(@onNull final StructNlMsgHdr header, @NonNull final StructPrefixMsg prefixmsg, @NonNull final IpPrefix prefix, long preferred, long valid)53     public RtNetlinkPrefixMessage(@NonNull final StructNlMsgHdr header,
54             @NonNull final StructPrefixMsg prefixmsg,
55             @NonNull final IpPrefix prefix,
56             long preferred, long valid) {
57         super(header);
58         mPrefixmsg = prefixmsg;
59         mPrefix = prefix;
60         mPreferredLifetime = preferred;
61         mValidLifetime = valid;
62     }
63 
RtNetlinkPrefixMessage(@onNull StructNlMsgHdr header)64     private RtNetlinkPrefixMessage(@NonNull StructNlMsgHdr header) {
65         this(header, null, null, 0 /* preferredLifetime */, 0 /* validLifetime */);
66     }
67 
68     @NonNull
getPrefixMsg()69     public StructPrefixMsg getPrefixMsg() {
70         return mPrefixmsg;
71     }
72 
73     @NonNull
getPrefix()74     public IpPrefix getPrefix() {
75         return mPrefix;
76     }
77 
getPreferredLifetime()78     public long getPreferredLifetime() {
79         return mPreferredLifetime;
80     }
81 
getValidLifetime()82     public long getValidLifetime() {
83         return mValidLifetime;
84     }
85 
86     /**
87      * Parse rtnetlink prefix message from {@link ByteBuffer}. This method must be called with a
88      * ByteBuffer that contains exactly one netlink message.
89      *
90      * RTM_NEWPREFIX Message Format:
91      *  +----------+- - -+-------------+- - -+---------------------+-----------------------+
92      *  | nlmsghdr | Pad |  prefixmsg  | Pad | PREFIX_ADDRESS attr | PREFIX_CACHEINFO attr |
93      *  +----------+- - -+-------------+- - -+---------------------+-----------------------+
94      *
95      * @param header netlink message header.
96      * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
97      */
98     @Nullable
parse(@onNull final StructNlMsgHdr header, @NonNull final ByteBuffer byteBuffer)99     public static RtNetlinkPrefixMessage parse(@NonNull final StructNlMsgHdr header,
100             @NonNull final ByteBuffer byteBuffer) {
101         try {
102             final RtNetlinkPrefixMessage msg = new RtNetlinkPrefixMessage(header);
103             msg.mPrefixmsg = StructPrefixMsg.parse(byteBuffer);
104 
105             // PREFIX_ADDRESS
106             final int baseOffset = byteBuffer.position();
107             StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(PREFIX_ADDRESS, byteBuffer);
108             if (nlAttr == null) return null;
109             final Inet6Address addr = (Inet6Address) nlAttr.getValueAsInetAddress();
110             if (addr == null) return null;
111             msg.mPrefix = new IpPrefix(addr, msg.mPrefixmsg.prefix_len);
112 
113             // PREFIX_CACHEINFO
114             byteBuffer.position(baseOffset);
115             nlAttr = StructNlAttr.findNextAttrOfType(PREFIX_CACHEINFO, byteBuffer);
116             if (nlAttr == null) return null;
117             final ByteBuffer buffer = nlAttr.getValueAsByteBuffer();
118             if (buffer == null) return null;
119             final StructPrefixCacheInfo cacheinfo = StructPrefixCacheInfo.parse(buffer);
120             msg.mPreferredLifetime = cacheinfo.preferred_time;
121             msg.mValidLifetime = cacheinfo.valid_time;
122 
123             return msg;
124         } catch (IllegalArgumentException e) {
125             return null;
126         }
127     }
128 
129     /**
130      * Write a rtnetlink prefix message to {@link ByteBuffer}.
131      */
132     @VisibleForTesting
pack(ByteBuffer byteBuffer)133     protected void pack(ByteBuffer byteBuffer) {
134         getHeader().pack(byteBuffer);
135         mPrefixmsg.pack(byteBuffer);
136 
137         // PREFIX_ADDRESS attribute
138         final StructNlAttr prefixAddress =
139                 new StructNlAttr(PREFIX_ADDRESS, mPrefix.getRawAddress());
140         prefixAddress.pack(byteBuffer);
141 
142         // PREFIX_CACHEINFO attribute
143         final StructPrefixCacheInfo cacheinfo =
144                 new StructPrefixCacheInfo(mPreferredLifetime, mValidLifetime);
145         final StructNlAttr prefixCacheinfo =
146                 new StructNlAttr(PREFIX_CACHEINFO, cacheinfo.writeToBytes());
147         prefixCacheinfo.pack(byteBuffer);
148     }
149 
150     @Override
toString()151     public String toString() {
152         return "RtNetlinkPrefixMessage{ "
153                 + "nlmsghdr{" + mHeader.toString(OsConstants.NETLINK_ROUTE) + "}, "
154                 + "prefixmsg{" + mPrefixmsg.toString() + "}, "
155                 + "IP Prefix{" + mPrefix + "}, "
156                 + "preferred lifetime{" + mPreferredLifetime + "}, "
157                 + "valid lifetime{" + mValidLifetime + "} "
158                 + "}";
159     }
160 }
161