• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.net.netlink;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 
22 import java.nio.ByteBuffer;
23 
24 
25 /**
26  * struct nlmsghdr
27  *
28  * see <linux_src>/include/uapi/linux/netlink.h
29  *
30  * @hide
31  */
32 public class StructNlMsgHdr {
33     // Already aligned.
34     public static final int STRUCT_SIZE = 16;
35 
36     public static final short NLM_F_REQUEST = 0x0001;
37     public static final short NLM_F_MULTI   = 0x0002;
38     public static final short NLM_F_ACK     = 0x0004;
39     public static final short NLM_F_ECHO    = 0x0008;
40     // Flags for a GET request.
41     public static final short NLM_F_ROOT    = 0x0100;
42     public static final short NLM_F_MATCH   = 0x0200;
43     public static final short NLM_F_DUMP    = NLM_F_ROOT|NLM_F_MATCH;
44     // Flags for a NEW request.
45     public static final short NLM_F_REPLACE   = 0x100;
46     public static final short NLM_F_EXCL      = 0x200;
47     public static final short NLM_F_CREATE    = 0x400;
48     public static final short NLM_F_APPEND    = 0x800;
49 
50     // TODO: Probably need to distinguish the flags which have the same value. For example,
51     // NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200).
stringForNlMsgFlags(short flags)52     public static String stringForNlMsgFlags(short flags) {
53         final StringBuilder sb = new StringBuilder();
54         if ((flags & NLM_F_REQUEST) != 0) {
55             sb.append("NLM_F_REQUEST");
56         }
57         if ((flags & NLM_F_MULTI) != 0) {
58             if (sb.length() > 0) { sb.append("|"); }
59             sb.append("NLM_F_MULTI");
60         }
61         if ((flags & NLM_F_ACK) != 0) {
62             if (sb.length() > 0) { sb.append("|"); }
63             sb.append("NLM_F_ACK");
64         }
65         if ((flags & NLM_F_ECHO) != 0) {
66             if (sb.length() > 0) { sb.append("|"); }
67             sb.append("NLM_F_ECHO");
68         }
69         if ((flags & NLM_F_ROOT) != 0) {
70             if (sb.length() > 0) { sb.append("|"); }
71             sb.append("NLM_F_ROOT");
72         }
73         if ((flags & NLM_F_MATCH) != 0) {
74             if (sb.length() > 0) { sb.append("|"); }
75             sb.append("NLM_F_MATCH");
76         }
77         return sb.toString();
78     }
79 
hasAvailableSpace(ByteBuffer byteBuffer)80     public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
81         return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
82     }
83 
parse(ByteBuffer byteBuffer)84     public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
85         if (!hasAvailableSpace(byteBuffer)) { return null; }
86 
87         // The ByteOrder must have already been set by the caller.  In most
88         // cases ByteOrder.nativeOrder() is correct, with the exception
89         // of usage within unittests.
90         final StructNlMsgHdr struct = new StructNlMsgHdr();
91         struct.nlmsg_len = byteBuffer.getInt();
92         struct.nlmsg_type = byteBuffer.getShort();
93         struct.nlmsg_flags = byteBuffer.getShort();
94         struct.nlmsg_seq = byteBuffer.getInt();
95         struct.nlmsg_pid = byteBuffer.getInt();
96 
97         if (struct.nlmsg_len < STRUCT_SIZE) {
98             // Malformed.
99             return null;
100         }
101         return struct;
102     }
103 
104     public int nlmsg_len;
105     public short nlmsg_type;
106     public short nlmsg_flags;
107     public int nlmsg_seq;
108     public int nlmsg_pid;
109 
StructNlMsgHdr()110     public StructNlMsgHdr() {
111         nlmsg_len = 0;
112         nlmsg_type = 0;
113         nlmsg_flags = 0;
114         nlmsg_seq = 0;
115         nlmsg_pid = 0;
116     }
117 
pack(ByteBuffer byteBuffer)118     public void pack(ByteBuffer byteBuffer) {
119         // The ByteOrder must have already been set by the caller.  In most
120         // cases ByteOrder.nativeOrder() is correct, with the possible
121         // exception of usage within unittests.
122         byteBuffer.putInt(nlmsg_len);
123         byteBuffer.putShort(nlmsg_type);
124         byteBuffer.putShort(nlmsg_flags);
125         byteBuffer.putInt(nlmsg_seq);
126         byteBuffer.putInt(nlmsg_pid);
127     }
128 
129     @Override
toString()130     public String toString() {
131         return toString(null /* unknown netlink family */);
132     }
133 
134     /**
135      * Transform a netlink header into a string. The netlink family is required for transforming
136      * a netlink type integer into a string.
137      * @param nlFamily netlink family. Using Integer will not incur autoboxing penalties because
138      *                 family values are small, and all Integer objects between -128 and 127 are
139      *                 statically cached. See Integer.IntegerCache.
140      * @return A list of header elements.
141      */
142     @NonNull
toString(@ullable Integer nlFamily)143     public String toString(@Nullable Integer nlFamily) {
144         final String typeStr = "" + nlmsg_type
145                 + "(" + (nlFamily == null
146                 ? "" : NetlinkConstants.stringForNlMsgType(nlmsg_type, nlFamily))
147                 + ")";
148         final String flagsStr = "" + nlmsg_flags
149                 + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
150         return "StructNlMsgHdr{ "
151                 + "nlmsg_len{" + nlmsg_len + "}, "
152                 + "nlmsg_type{" + typeStr + "}, "
153                 + "nlmsg_flags{" + flagsStr + ")}, "
154                 + "nlmsg_seq{" + nlmsg_seq + "}, "
155                 + "nlmsg_pid{" + nlmsg_pid + "} "
156                 + "}";
157     }
158 }
159