StructNlMsgHdr.java revision 6193aa3305bc2aa5b7f0a983f4b08c99065cfb82
1/*
2 * Copyright (C) 2015 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
17package android.net.netlink;
18
19import android.net.netlink.NetlinkConstants;
20import java.nio.ByteBuffer;
21
22
23/**
24 * struct nlmsghdr
25 *
26 * see <linux_src>/include/uapi/linux/netlink.h
27 *
28 * @hide
29 */
30public class StructNlMsgHdr {
31    // Already aligned.
32    public static final int STRUCT_SIZE = 16;
33
34    public static final short NLM_F_REQUEST = 0x0001;
35    public static final short NLM_F_MULTI   = 0x0002;
36    public static final short NLM_F_ACK     = 0x0004;
37    public static final short NLM_F_ECHO    = 0x0008;
38    // Flags for a GET request.
39    public static final short NLM_F_ROOT    = 0x0100;
40    public static final short NLM_F_MATCH   = 0x0200;
41    public static final short NLM_F_DUMP    = NLM_F_ROOT|NLM_F_MATCH;
42
43    public static String stringForNlMsgFlags(short flags) {
44        final StringBuilder sb = new StringBuilder();
45        if ((flags & NLM_F_REQUEST) != 0) {
46            sb.append("NLM_F_REQUEST");
47        }
48        if ((flags & NLM_F_MULTI) != 0) {
49            if (sb.length() > 0) { sb.append("|"); }
50            sb.append("NLM_F_MULTI");
51        }
52        if ((flags & NLM_F_ACK) != 0) {
53            if (sb.length() > 0) { sb.append("|"); }
54            sb.append("NLM_F_ACK");
55        }
56        if ((flags & NLM_F_ECHO) != 0) {
57            if (sb.length() > 0) { sb.append("|"); }
58            sb.append("NLM_F_ECHO");
59        }
60        if ((flags & NLM_F_ROOT) != 0) {
61            if (sb.length() > 0) { sb.append("|"); }
62            sb.append("NLM_F_ROOT");
63        }
64        if ((flags & NLM_F_MATCH) != 0) {
65            if (sb.length() > 0) { sb.append("|"); }
66            sb.append("NLM_F_MATCH");
67        }
68        return sb.toString();
69    }
70
71    public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
72        return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
73    }
74
75    public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
76        if (!hasAvailableSpace(byteBuffer)) { return null; }
77
78        // The ByteOrder must have already been set by the caller.  In most
79        // cases ByteOrder.nativeOrder() is correct, with the exception
80        // of usage within unittests.
81        final StructNlMsgHdr struct = new StructNlMsgHdr();
82        struct.nlmsg_len = byteBuffer.getInt();
83        struct.nlmsg_type = byteBuffer.getShort();
84        struct.nlmsg_flags = byteBuffer.getShort();
85        struct.nlmsg_seq = byteBuffer.getInt();
86        struct.nlmsg_pid = byteBuffer.getInt();
87
88        if (struct.nlmsg_len < STRUCT_SIZE) {
89            // Malformed.
90            return null;
91        }
92        return struct;
93    }
94
95    public int nlmsg_len;
96    public short nlmsg_type;
97    public short nlmsg_flags;
98    public int nlmsg_seq;
99    public int nlmsg_pid;
100
101    public StructNlMsgHdr() {
102        nlmsg_len = 0;
103        nlmsg_type = 0;
104        nlmsg_flags = 0;
105        nlmsg_seq = 0;
106        nlmsg_pid = 0;
107    }
108
109    public boolean pack(ByteBuffer byteBuffer) {
110        if (!hasAvailableSpace(byteBuffer)) { return false; }
111
112        // The ByteOrder must have already been set by the caller.  In most
113        // cases ByteOrder.nativeOrder() is correct, with the possible
114        // exception of usage within unittests.
115        byteBuffer.putInt(nlmsg_len);
116        byteBuffer.putShort(nlmsg_type);
117        byteBuffer.putShort(nlmsg_flags);
118        byteBuffer.putInt(nlmsg_seq);
119        byteBuffer.putInt(nlmsg_pid);
120        return true;
121    }
122
123    @Override
124    public String toString() {
125        final String typeStr = "" + nlmsg_type
126                + "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")";
127        final String flagsStr = "" + nlmsg_flags
128                + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
129        return "StructNlMsgHdr{ "
130                + "nlmsg_len{" + nlmsg_len + "}, "
131                + "nlmsg_type{" + typeStr + "}, "
132                + "nlmsg_flags{" + flagsStr + ")}, "
133                + "nlmsg_seq{" + nlmsg_seq + "}, "
134                + "nlmsg_pid{" + nlmsg_pid + "} "
135                + "}";
136    }
137}
138