summaryrefslogtreecommitdiff
path: root/common/device/com/android/net/module/util/netlink/NetlinkConstants.java
blob: 44c51d8a8c302f9beac8a63e909612e5fb283403 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.net.module.util.netlink;

import android.system.OsConstants;

import androidx.annotation.NonNull;

import java.nio.ByteBuffer;

/**
 * Various constants and static helper methods for netlink communications.
 *
 * Values taken from:
 *
 *     include/uapi/linux/netfilter/nfnetlink.h
 *     include/uapi/linux/netfilter/nfnetlink_conntrack.h
 *     include/uapi/linux/netlink.h
 *     include/uapi/linux/rtnetlink.h
 *
 * @hide
 */
public class NetlinkConstants {
    private NetlinkConstants() {}

    public static final int NLA_ALIGNTO = 4;
    /**
     * Flag for dumping struct tcp_info.
     * Corresponding to enum definition in external/strace/linux/inet_diag.h.
     */
    public static final int INET_DIAG_MEMINFO = 1;

    public static final int SOCKDIAG_MSG_HEADER_SIZE =
            StructNlMsgHdr.STRUCT_SIZE + StructInetDiagMsg.STRUCT_SIZE;

    /**
     * Get the aligned length based on a Short type number.
     */
    public static final int alignedLengthOf(short length) {
        final int intLength = (int) length & 0xffff;
        return alignedLengthOf(intLength);
    }

    /**
     * Get the aligned length based on a Integer type number.
     */
    public static final int alignedLengthOf(int length) {
        if (length <= 0) return 0;
        return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
    }

    /**
     * Convert a address family type to a string.
     */
    public static String stringForAddressFamily(int family) {
        if (family == OsConstants.AF_INET) return "AF_INET";
        if (family == OsConstants.AF_INET6) return "AF_INET6";
        if (family == OsConstants.AF_NETLINK) return "AF_NETLINK";
        if (family == OsConstants.AF_UNSPEC) return "AF_UNSPEC";
        return String.valueOf(family);
    }

    /**
     * Convert a protocol type to a string.
     */
    public static String stringForProtocol(int protocol) {
        if (protocol == OsConstants.IPPROTO_TCP) return "IPPROTO_TCP";
        if (protocol == OsConstants.IPPROTO_UDP) return "IPPROTO_UDP";
        return String.valueOf(protocol);
    }

    /**
     * Convert a byte array to a hexadecimal string.
     */
    public static String hexify(byte[] bytes) {
        if (bytes == null) return "(null)";
        return toHexString(bytes, 0, bytes.length);
    }

    /**
     * Convert a {@link ByteBuffer} to a hexadecimal string.
     */
    public static String hexify(ByteBuffer buffer) {
        if (buffer == null) return "(null)";
        return toHexString(
                buffer.array(), buffer.position(), buffer.remaining());
    }

    // Known values for struct nlmsghdr nlm_type.
    public static final short NLMSG_NOOP                    = 1;   // Nothing
    public static final short NLMSG_ERROR                   = 2;   // Error
    public static final short NLMSG_DONE                    = 3;   // End of a dump
    public static final short NLMSG_OVERRUN                 = 4;   // Data lost
    public static final short NLMSG_MAX_RESERVED            = 15;  // Max reserved value

    public static final short RTM_NEWLINK                   = 16;
    public static final short RTM_DELLINK                   = 17;
    public static final short RTM_GETLINK                   = 18;
    public static final short RTM_SETLINK                   = 19;
    public static final short RTM_NEWADDR                   = 20;
    public static final short RTM_DELADDR                   = 21;
    public static final short RTM_GETADDR                   = 22;
    public static final short RTM_NEWROUTE                  = 24;
    public static final short RTM_DELROUTE                  = 25;
    public static final short RTM_GETROUTE                  = 26;
    public static final short RTM_NEWNEIGH                  = 28;
    public static final short RTM_DELNEIGH                  = 29;
    public static final short RTM_GETNEIGH                  = 30;
    public static final short RTM_NEWRULE                   = 32;
    public static final short RTM_DELRULE                   = 33;
    public static final short RTM_GETRULE                   = 34;
    public static final short RTM_NEWNDUSEROPT              = 68;

    // Netfilter netlink message types are presented by two bytes: high byte subsystem and
    // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in
    // include/uapi/linux/netfilter/nfnetlink.h
    public static final short NFNL_SUBSYS_CTNETLINK         = 1;

    public static final short IPCTNL_MSG_CT_NEW             = 0;
    public static final short IPCTNL_MSG_CT_GET             = 1;
    public static final short IPCTNL_MSG_CT_DELETE          = 2;
    public static final short IPCTNL_MSG_CT_GET_CTRZERO     = 3;
    public static final short IPCTNL_MSG_CT_GET_STATS_CPU   = 4;
    public static final short IPCTNL_MSG_CT_GET_STATS       = 5;
    public static final short IPCTNL_MSG_CT_GET_DYING       = 6;
    public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7;

    /* see include/uapi/linux/sock_diag.h */
    public static final short SOCK_DIAG_BY_FAMILY = 20;
    public static final short SOCK_DESTROY = 21;

    // Netlink groups.
    public static final int RTMGRP_LINK = 1;
    public static final int RTMGRP_IPV4_IFADDR = 0x10;
    public static final int RTMGRP_IPV6_IFADDR = 0x100;
    public static final int RTMGRP_IPV6_ROUTE  = 0x400;
    public static final int RTNLGRP_ND_USEROPT = 20;
    public static final int RTMGRP_ND_USEROPT = 1 << (RTNLGRP_ND_USEROPT - 1);

    // Device flags.
    public static final int IFF_UP       = 1 << 0;
    public static final int IFF_LOWER_UP = 1 << 16;

    // Known values for struct rtmsg rtm_protocol.
    public static final short RTPROT_KERNEL     = 2;
    public static final short RTPROT_RA         = 9;

    // Known values for struct rtmsg rtm_scope.
    public static final short RT_SCOPE_UNIVERSE = 0;

    // Known values for struct rtmsg rtm_type.
    public static final short RTN_UNICAST       = 1;

    // Known values for struct rtmsg rtm_flags.
    public static final int RTM_F_CLONED        = 0x200;

    /**
     * Convert a netlink message type to a string for control message.
     */
    @NonNull
    private static String stringForCtlMsgType(short nlmType) {
        switch (nlmType) {
            case NLMSG_NOOP: return "NLMSG_NOOP";
            case NLMSG_ERROR: return "NLMSG_ERROR";
            case NLMSG_DONE: return "NLMSG_DONE";
            case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
            default: return "unknown control message type: " + String.valueOf(nlmType);
        }
    }

    /**
     * Convert a netlink message type to a string for NETLINK_ROUTE.
     */
    @NonNull
    private static String stringForRtMsgType(short nlmType) {
        switch (nlmType) {
            case RTM_NEWLINK: return "RTM_NEWLINK";
            case RTM_DELLINK: return "RTM_DELLINK";
            case RTM_GETLINK: return "RTM_GETLINK";
            case RTM_SETLINK: return "RTM_SETLINK";
            case RTM_NEWADDR: return "RTM_NEWADDR";
            case RTM_DELADDR: return "RTM_DELADDR";
            case RTM_GETADDR: return "RTM_GETADDR";
            case RTM_NEWROUTE: return "RTM_NEWROUTE";
            case RTM_DELROUTE: return "RTM_DELROUTE";
            case RTM_GETROUTE: return "RTM_GETROUTE";
            case RTM_NEWNEIGH: return "RTM_NEWNEIGH";
            case RTM_DELNEIGH: return "RTM_DELNEIGH";
            case RTM_GETNEIGH: return "RTM_GETNEIGH";
            case RTM_NEWRULE: return "RTM_NEWRULE";
            case RTM_DELRULE: return "RTM_DELRULE";
            case RTM_GETRULE: return "RTM_GETRULE";
            case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT";
            default: return "unknown RTM type: " + String.valueOf(nlmType);
        }
    }

    /**
     * Convert a netlink message type to a string for NETLINK_INET_DIAG.
     */
    @NonNull
    private static String stringForInetDiagMsgType(short nlmType) {
        switch (nlmType) {
            case SOCK_DIAG_BY_FAMILY: return "SOCK_DIAG_BY_FAMILY";
            default: return "unknown SOCK_DIAG type: " + String.valueOf(nlmType);
        }
    }

    /**
     * Convert a netlink message type to a string for NETLINK_NETFILTER.
     */
    @NonNull
    private static String stringForNfMsgType(short nlmType) {
        final byte subsysId = (byte) (nlmType >> 8);
        final byte msgType = (byte) nlmType;
        switch (subsysId) {
            case NFNL_SUBSYS_CTNETLINK:
                switch (msgType) {
                    case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW";
                    case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET";
                    case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE";
                    case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO";
                    case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU";
                    case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS";
                    case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING";
                    case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED";
                }
                break;
        }
        return "unknown NETFILTER type: " + String.valueOf(nlmType);
    }

    /**
     * Convert a netlink message type to a string by netlink family.
     */
    @NonNull
    public static String stringForNlMsgType(short nlmType, int nlFamily) {
        // Reserved control messages. The netlink family is ignored.
        // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h.
        if (nlmType <= NLMSG_MAX_RESERVED) return stringForCtlMsgType(nlmType);

        // Netlink family messages. The netlink family is required. Note that the reason for using
        // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are
        // not constant.
        if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType);
        if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType);
        if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType);

        return "unknown type: " + String.valueOf(nlmType);
    }

    private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E', 'F' };
    /**
     * Convert a byte array to a hexadecimal string.
     */
    public static String toHexString(byte[] array, int offset, int length) {
        char[] buf = new char[length * 2];

        int bufIndex = 0;
        for (int i = offset; i < offset + length; i++) {
            byte b = array[i];
            buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
            buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
        }

        return new String(buf);
    }
}