StructNlMsgHdr.java revision 9ce5d602cd5d732ae10efe0b648b43ddf60d65c9
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    // Flags for a NEW request.
43    public static final short NLM_F_REPLACE   = 0x100;
44    public static final short NLM_F_EXCL      = 0x200;
45    public static final short NLM_F_CREATE    = 0x400;
46    public static final short NLM_F_APPEND    = 0x800;
47
48
49    public static String stringForNlMsgFlags(short flags) {
50        final StringBuilder sb = new StringBuilder();
51        if ((flags & NLM_F_REQUEST) != 0) {
52            sb.append("NLM_F_REQUEST");
53        }
54        if ((flags & NLM_F_MULTI) != 0) {
55            if (sb.length() > 0) { sb.append("|"); }
56            sb.append("NLM_F_MULTI");
57        }
58        if ((flags & NLM_F_ACK) != 0) {
59            if (sb.length() > 0) { sb.append("|"); }
60            sb.append("NLM_F_ACK");
61        }
62        if ((flags & NLM_F_ECHO) != 0) {
63            if (sb.length() > 0) { sb.append("|"); }
64            sb.append("NLM_F_ECHO");
65        }
66        if ((flags & NLM_F_ROOT) != 0) {
67            if (sb.length() > 0) { sb.append("|"); }
68            sb.append("NLM_F_ROOT");
69        }
70        if ((flags & NLM_F_MATCH) != 0) {
71            if (sb.length() > 0) { sb.append("|"); }
72            sb.append("NLM_F_MATCH");
73        }
74        return sb.toString();
75    }
76
77    public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
78        return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
79    }
80
81    public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
82        if (!hasAvailableSpace(byteBuffer)) { return null; }
83
84        // The ByteOrder must have already been set by the caller.  In most
85        // cases ByteOrder.nativeOrder() is correct, with the exception
86        // of usage within unittests.
87        final StructNlMsgHdr struct = new StructNlMsgHdr();
88        struct.nlmsg_len = byteBuffer.getInt();
89        struct.nlmsg_type = byteBuffer.getShort();
90        struct.nlmsg_flags = byteBuffer.getShort();
91        struct.nlmsg_seq = byteBuffer.getInt();
92        struct.nlmsg_pid = byteBuffer.getInt();
93
94        if (struct.nlmsg_len < STRUCT_SIZE) {
95            // Malformed.
96            return null;
97        }
98        return struct;
99    }
100
101    public int nlmsg_len;
102    public short nlmsg_type;
103    public short nlmsg_flags;
104    public int nlmsg_seq;
105    public int nlmsg_pid;
106
107    public StructNlMsgHdr() {
108        nlmsg_len = 0;
109        nlmsg_type = 0;
110        nlmsg_flags = 0;
111        nlmsg_seq = 0;
112        nlmsg_pid = 0;
113    }
114
115    public void pack(ByteBuffer byteBuffer) {
116        // The ByteOrder must have already been set by the caller.  In most
117        // cases ByteOrder.nativeOrder() is correct, with the possible
118        // exception of usage within unittests.
119        byteBuffer.putInt(nlmsg_len);
120        byteBuffer.putShort(nlmsg_type);
121        byteBuffer.putShort(nlmsg_flags);
122        byteBuffer.putInt(nlmsg_seq);
123        byteBuffer.putInt(nlmsg_pid);
124    }
125
126    @Override
127    public String toString() {
128        final String typeStr = "" + nlmsg_type
129                + "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")";
130        final String flagsStr = "" + nlmsg_flags
131                + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
132        return "StructNlMsgHdr{ "
133                + "nlmsg_len{" + nlmsg_len + "}, "
134                + "nlmsg_type{" + typeStr + "}, "
135                + "nlmsg_flags{" + flagsStr + ")}, "
136                + "nlmsg_seq{" + nlmsg_seq + "}, "
137                + "nlmsg_pid{" + nlmsg_pid + "} "
138                + "}";
139    }
140}
141