• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.net.module.util.netlink;
18 
19 import android.system.OsConstants;
20 
21 import androidx.annotation.NonNull;
22 
23 import java.nio.ByteBuffer;
24 
25 /**
26  * Various constants and static helper methods for netlink communications.
27  *
28  * Values taken from:
29  *
30  *     include/uapi/linux/netfilter/nfnetlink.h
31  *     include/uapi/linux/netfilter/nfnetlink_conntrack.h
32  *     include/uapi/linux/netlink.h
33  *     include/uapi/linux/rtnetlink.h
34  *
35  * @hide
36  */
37 public class NetlinkConstants {
NetlinkConstants()38     private NetlinkConstants() {}
39 
40     public static final int NLA_ALIGNTO = 4;
41     /**
42      * Flag for dumping struct tcp_info.
43      * Corresponding to enum definition in external/strace/linux/inet_diag.h.
44      */
45     public static final int INET_DIAG_MEMINFO = 1;
46 
47     public static final int SOCKDIAG_MSG_HEADER_SIZE =
48             StructNlMsgHdr.STRUCT_SIZE + StructInetDiagMsg.STRUCT_SIZE;
49 
50     /**
51      * Get the aligned length based on a Short type number.
52      */
alignedLengthOf(short length)53     public static final int alignedLengthOf(short length) {
54         final int intLength = (int) length & 0xffff;
55         return alignedLengthOf(intLength);
56     }
57 
58     /**
59      * Get the aligned length based on a Integer type number.
60      */
alignedLengthOf(int length)61     public static final int alignedLengthOf(int length) {
62         if (length <= 0) return 0;
63         return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
64     }
65 
66     /**
67      * Convert a address family type to a string.
68      */
stringForAddressFamily(int family)69     public static String stringForAddressFamily(int family) {
70         if (family == OsConstants.AF_INET) return "AF_INET";
71         if (family == OsConstants.AF_INET6) return "AF_INET6";
72         if (family == OsConstants.AF_NETLINK) return "AF_NETLINK";
73         if (family == OsConstants.AF_UNSPEC) return "AF_UNSPEC";
74         return String.valueOf(family);
75     }
76 
77     /**
78      * Convert a protocol type to a string.
79      */
stringForProtocol(int protocol)80     public static String stringForProtocol(int protocol) {
81         if (protocol == OsConstants.IPPROTO_TCP) return "IPPROTO_TCP";
82         if (protocol == OsConstants.IPPROTO_UDP) return "IPPROTO_UDP";
83         return String.valueOf(protocol);
84     }
85 
86     /**
87      * Convert a byte array to a hexadecimal string.
88      */
hexify(byte[] bytes)89     public static String hexify(byte[] bytes) {
90         if (bytes == null) return "(null)";
91         return toHexString(bytes, 0, bytes.length);
92     }
93 
94     /**
95      * Convert a {@link ByteBuffer} to a hexadecimal string.
96      */
hexify(ByteBuffer buffer)97     public static String hexify(ByteBuffer buffer) {
98         if (buffer == null) return "(null)";
99         return toHexString(
100                 buffer.array(), buffer.position(), buffer.remaining());
101     }
102 
103     // Known values for struct nlmsghdr nlm_type.
104     public static final short NLMSG_NOOP                    = 1;   // Nothing
105     public static final short NLMSG_ERROR                   = 2;   // Error
106     public static final short NLMSG_DONE                    = 3;   // End of a dump
107     public static final short NLMSG_OVERRUN                 = 4;   // Data lost
108     public static final short NLMSG_MAX_RESERVED            = 15;  // Max reserved value
109 
110     public static final short RTM_NEWLINK                   = 16;
111     public static final short RTM_DELLINK                   = 17;
112     public static final short RTM_GETLINK                   = 18;
113     public static final short RTM_SETLINK                   = 19;
114     public static final short RTM_NEWADDR                   = 20;
115     public static final short RTM_DELADDR                   = 21;
116     public static final short RTM_GETADDR                   = 22;
117     public static final short RTM_NEWROUTE                  = 24;
118     public static final short RTM_DELROUTE                  = 25;
119     public static final short RTM_GETROUTE                  = 26;
120     public static final short RTM_NEWNEIGH                  = 28;
121     public static final short RTM_DELNEIGH                  = 29;
122     public static final short RTM_GETNEIGH                  = 30;
123     public static final short RTM_NEWRULE                   = 32;
124     public static final short RTM_DELRULE                   = 33;
125     public static final short RTM_GETRULE                   = 34;
126     public static final short RTM_NEWNDUSEROPT              = 68;
127 
128     // Netfilter netlink message types are presented by two bytes: high byte subsystem and
129     // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in
130     // include/uapi/linux/netfilter/nfnetlink.h
131     public static final short NFNL_SUBSYS_CTNETLINK         = 1;
132 
133     public static final short IPCTNL_MSG_CT_NEW             = 0;
134     public static final short IPCTNL_MSG_CT_GET             = 1;
135     public static final short IPCTNL_MSG_CT_DELETE          = 2;
136     public static final short IPCTNL_MSG_CT_GET_CTRZERO     = 3;
137     public static final short IPCTNL_MSG_CT_GET_STATS_CPU   = 4;
138     public static final short IPCTNL_MSG_CT_GET_STATS       = 5;
139     public static final short IPCTNL_MSG_CT_GET_DYING       = 6;
140     public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7;
141 
142     /* see include/uapi/linux/sock_diag.h */
143     public static final short SOCK_DIAG_BY_FAMILY = 20;
144 
145     // Netlink groups.
146     public static final int RTMGRP_LINK = 1;
147     public static final int RTMGRP_IPV4_IFADDR = 0x10;
148     public static final int RTMGRP_IPV6_IFADDR = 0x100;
149     public static final int RTMGRP_IPV6_ROUTE  = 0x400;
150     public static final int RTNLGRP_ND_USEROPT = 20;
151     public static final int RTMGRP_ND_USEROPT = 1 << (RTNLGRP_ND_USEROPT - 1);
152 
153     // Device flags.
154     public static final int IFF_UP       = 1 << 0;
155     public static final int IFF_LOWER_UP = 1 << 16;
156 
157     // Known values for struct rtmsg rtm_protocol.
158     public static final short RTPROT_KERNEL     = 2;
159     public static final short RTPROT_RA         = 9;
160 
161     // Known values for struct rtmsg rtm_scope.
162     public static final short RT_SCOPE_UNIVERSE = 0;
163 
164     // Known values for struct rtmsg rtm_type.
165     public static final short RTN_UNICAST       = 1;
166 
167     // Known values for struct rtmsg rtm_flags.
168     public static final int RTM_F_CLONED        = 0x200;
169 
170     /**
171      * Convert a netlink message type to a string for control message.
172      */
173     @NonNull
stringForCtlMsgType(short nlmType)174     private static String stringForCtlMsgType(short nlmType) {
175         switch (nlmType) {
176             case NLMSG_NOOP: return "NLMSG_NOOP";
177             case NLMSG_ERROR: return "NLMSG_ERROR";
178             case NLMSG_DONE: return "NLMSG_DONE";
179             case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
180             default: return "unknown control message type: " + String.valueOf(nlmType);
181         }
182     }
183 
184     /**
185      * Convert a netlink message type to a string for NETLINK_ROUTE.
186      */
187     @NonNull
stringForRtMsgType(short nlmType)188     private static String stringForRtMsgType(short nlmType) {
189         switch (nlmType) {
190             case RTM_NEWLINK: return "RTM_NEWLINK";
191             case RTM_DELLINK: return "RTM_DELLINK";
192             case RTM_GETLINK: return "RTM_GETLINK";
193             case RTM_SETLINK: return "RTM_SETLINK";
194             case RTM_NEWADDR: return "RTM_NEWADDR";
195             case RTM_DELADDR: return "RTM_DELADDR";
196             case RTM_GETADDR: return "RTM_GETADDR";
197             case RTM_NEWROUTE: return "RTM_NEWROUTE";
198             case RTM_DELROUTE: return "RTM_DELROUTE";
199             case RTM_GETROUTE: return "RTM_GETROUTE";
200             case RTM_NEWNEIGH: return "RTM_NEWNEIGH";
201             case RTM_DELNEIGH: return "RTM_DELNEIGH";
202             case RTM_GETNEIGH: return "RTM_GETNEIGH";
203             case RTM_NEWRULE: return "RTM_NEWRULE";
204             case RTM_DELRULE: return "RTM_DELRULE";
205             case RTM_GETRULE: return "RTM_GETRULE";
206             case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT";
207             default: return "unknown RTM type: " + String.valueOf(nlmType);
208         }
209     }
210 
211     /**
212      * Convert a netlink message type to a string for NETLINK_INET_DIAG.
213      */
214     @NonNull
stringForInetDiagMsgType(short nlmType)215     private static String stringForInetDiagMsgType(short nlmType) {
216         switch (nlmType) {
217             case SOCK_DIAG_BY_FAMILY: return "SOCK_DIAG_BY_FAMILY";
218             default: return "unknown SOCK_DIAG type: " + String.valueOf(nlmType);
219         }
220     }
221 
222     /**
223      * Convert a netlink message type to a string for NETLINK_NETFILTER.
224      */
225     @NonNull
stringForNfMsgType(short nlmType)226     private static String stringForNfMsgType(short nlmType) {
227         final byte subsysId = (byte) (nlmType >> 8);
228         final byte msgType = (byte) nlmType;
229         switch (subsysId) {
230             case NFNL_SUBSYS_CTNETLINK:
231                 switch (msgType) {
232                     case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW";
233                     case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET";
234                     case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE";
235                     case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO";
236                     case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU";
237                     case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS";
238                     case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING";
239                     case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED";
240                 }
241                 break;
242         }
243         return "unknown NETFILTER type: " + String.valueOf(nlmType);
244     }
245 
246     /**
247      * Convert a netlink message type to a string by netlink family.
248      */
249     @NonNull
stringForNlMsgType(short nlmType, int nlFamily)250     public static String stringForNlMsgType(short nlmType, int nlFamily) {
251         // Reserved control messages. The netlink family is ignored.
252         // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h.
253         if (nlmType <= NLMSG_MAX_RESERVED) return stringForCtlMsgType(nlmType);
254 
255         // Netlink family messages. The netlink family is required. Note that the reason for using
256         // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are
257         // not constant.
258         if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType);
259         if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType);
260         if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType);
261 
262         return "unknown type: " + String.valueOf(nlmType);
263     }
264 
265     private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
266             'A', 'B', 'C', 'D', 'E', 'F' };
267     /**
268      * Convert a byte array to a hexadecimal string.
269      */
toHexString(byte[] array, int offset, int length)270     public static String toHexString(byte[] array, int offset, int length) {
271         char[] buf = new char[length * 2];
272 
273         int bufIndex = 0;
274         for (int i = offset; i < offset + length; i++) {
275             byte b = array[i];
276             buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
277             buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
278         }
279 
280         return new String(buf);
281     }
282 }
283