• 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 android.net.netlink;
18 
19 import android.annotation.NonNull;
20 import android.system.OsConstants;
21 
22 import java.nio.ByteBuffer;
23 
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 
alignedLengthOf(short length)50     public static final int alignedLengthOf(short length) {
51         final int intLength = (int) length & 0xffff;
52         return alignedLengthOf(intLength);
53     }
54 
alignedLengthOf(int length)55     public static final int alignedLengthOf(int length) {
56         if (length <= 0) { return 0; }
57         return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
58     }
59 
stringForAddressFamily(int family)60     public static String stringForAddressFamily(int family) {
61         if (family == OsConstants.AF_INET) { return "AF_INET"; }
62         if (family == OsConstants.AF_INET6) { return "AF_INET6"; }
63         if (family == OsConstants.AF_NETLINK) { return "AF_NETLINK"; }
64         return String.valueOf(family);
65     }
66 
stringForProtocol(int protocol)67     public static String stringForProtocol(int protocol) {
68         if (protocol == OsConstants.IPPROTO_TCP) { return "IPPROTO_TCP"; }
69         if (protocol == OsConstants.IPPROTO_UDP) { return "IPPROTO_UDP"; }
70         return String.valueOf(protocol);
71     }
72 
hexify(byte[] bytes)73     public static String hexify(byte[] bytes) {
74         if (bytes == null) { return "(null)"; }
75         return toHexString(bytes, 0, bytes.length);
76     }
77 
hexify(ByteBuffer buffer)78     public static String hexify(ByteBuffer buffer) {
79         if (buffer == null) { return "(null)"; }
80         return toHexString(
81                 buffer.array(), buffer.position(), buffer.remaining());
82     }
83 
84     // Known values for struct nlmsghdr nlm_type.
85     public static final short NLMSG_NOOP                    = 1;   // Nothing
86     public static final short NLMSG_ERROR                   = 2;   // Error
87     public static final short NLMSG_DONE                    = 3;   // End of a dump
88     public static final short NLMSG_OVERRUN                 = 4;   // Data lost
89     public static final short NLMSG_MAX_RESERVED            = 15;  // Max reserved value
90 
91     public static final short RTM_NEWLINK                   = 16;
92     public static final short RTM_DELLINK                   = 17;
93     public static final short RTM_GETLINK                   = 18;
94     public static final short RTM_SETLINK                   = 19;
95     public static final short RTM_NEWADDR                   = 20;
96     public static final short RTM_DELADDR                   = 21;
97     public static final short RTM_GETADDR                   = 22;
98     public static final short RTM_NEWROUTE                  = 24;
99     public static final short RTM_DELROUTE                  = 25;
100     public static final short RTM_GETROUTE                  = 26;
101     public static final short RTM_NEWNEIGH                  = 28;
102     public static final short RTM_DELNEIGH                  = 29;
103     public static final short RTM_GETNEIGH                  = 30;
104     public static final short RTM_NEWRULE                   = 32;
105     public static final short RTM_DELRULE                   = 33;
106     public static final short RTM_GETRULE                   = 34;
107     public static final short RTM_NEWNDUSEROPT              = 68;
108 
109     // Netfilter netlink message types are presented by two bytes: high byte subsystem and
110     // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in
111     // include/uapi/linux/netfilter/nfnetlink.h
112     public static final short NFNL_SUBSYS_CTNETLINK         = 1;
113 
114     public static final short IPCTNL_MSG_CT_NEW             = 0;
115     public static final short IPCTNL_MSG_CT_GET             = 1;
116     public static final short IPCTNL_MSG_CT_DELETE          = 2;
117     public static final short IPCTNL_MSG_CT_GET_CTRZERO     = 3;
118     public static final short IPCTNL_MSG_CT_GET_STATS_CPU   = 4;
119     public static final short IPCTNL_MSG_CT_GET_STATS       = 5;
120     public static final short IPCTNL_MSG_CT_GET_DYING       = 6;
121     public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7;
122 
123     /* see include/uapi/linux/sock_diag.h */
124     public static final short SOCK_DIAG_BY_FAMILY = 20;
125 
126     // Netlink groups.
127     public static final int RTNLGRP_ND_USEROPT = 20;
128     public static final int RTMGRP_ND_USEROPT = 1 << (RTNLGRP_ND_USEROPT - 1);
129 
130     /**
131      * Convert a netlink message type to a string for control message.
132      */
133     @NonNull
stringForCtlMsgType(short nlmType)134     private static String stringForCtlMsgType(short nlmType) {
135         switch (nlmType) {
136             case NLMSG_NOOP: return "NLMSG_NOOP";
137             case NLMSG_ERROR: return "NLMSG_ERROR";
138             case NLMSG_DONE: return "NLMSG_DONE";
139             case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
140             default: return "unknown control message type: " + String.valueOf(nlmType);
141         }
142     }
143 
144     /**
145      * Convert a netlink message type to a string for NETLINK_ROUTE.
146      */
147     @NonNull
stringForRtMsgType(short nlmType)148     private static String stringForRtMsgType(short nlmType) {
149         switch (nlmType) {
150             case RTM_NEWLINK: return "RTM_NEWLINK";
151             case RTM_DELLINK: return "RTM_DELLINK";
152             case RTM_GETLINK: return "RTM_GETLINK";
153             case RTM_SETLINK: return "RTM_SETLINK";
154             case RTM_NEWADDR: return "RTM_NEWADDR";
155             case RTM_DELADDR: return "RTM_DELADDR";
156             case RTM_GETADDR: return "RTM_GETADDR";
157             case RTM_NEWROUTE: return "RTM_NEWROUTE";
158             case RTM_DELROUTE: return "RTM_DELROUTE";
159             case RTM_GETROUTE: return "RTM_GETROUTE";
160             case RTM_NEWNEIGH: return "RTM_NEWNEIGH";
161             case RTM_DELNEIGH: return "RTM_DELNEIGH";
162             case RTM_GETNEIGH: return "RTM_GETNEIGH";
163             case RTM_NEWRULE: return "RTM_NEWRULE";
164             case RTM_DELRULE: return "RTM_DELRULE";
165             case RTM_GETRULE: return "RTM_GETRULE";
166             case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT";
167             default: return "unknown RTM type: " + String.valueOf(nlmType);
168         }
169     }
170 
171     /**
172      * Convert a netlink message type to a string for NETLINK_INET_DIAG.
173      */
174     @NonNull
stringForInetDiagMsgType(short nlmType)175     private static String stringForInetDiagMsgType(short nlmType) {
176         switch (nlmType) {
177             case SOCK_DIAG_BY_FAMILY: return "SOCK_DIAG_BY_FAMILY";
178             default: return "unknown SOCK_DIAG type: " + String.valueOf(nlmType);
179         }
180     }
181 
182     /**
183      * Convert a netlink message type to a string for NETLINK_NETFILTER.
184      */
185     @NonNull
stringForNfMsgType(short nlmType)186     private static String stringForNfMsgType(short nlmType) {
187         final byte subsysId = (byte) (nlmType >> 8);
188         final byte msgType = (byte) nlmType;
189         switch (subsysId) {
190             case NFNL_SUBSYS_CTNETLINK:
191                 switch (msgType) {
192                     case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW";
193                     case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET";
194                     case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE";
195                     case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO";
196                     case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU";
197                     case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS";
198                     case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING";
199                     case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED";
200                 }
201                 break;
202         }
203         return "unknown NETFILTER type: " + String.valueOf(nlmType);
204     }
205 
206     /**
207      * Convert a netlink message type to a string by netlink family.
208      */
209     @NonNull
stringForNlMsgType(short nlmType, int nlFamily)210     public static String stringForNlMsgType(short nlmType, int nlFamily) {
211         // Reserved control messages. The netlink family is ignored.
212         // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h.
213         if (nlmType <= NLMSG_MAX_RESERVED) return stringForCtlMsgType(nlmType);
214 
215         // Netlink family messages. The netlink family is required. Note that the reason for using
216         // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are
217         // not constant.
218         if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType);
219         if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType);
220         if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType);
221 
222         return "unknown type: " + String.valueOf(nlmType);
223     }
224 
225     private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
226             'A', 'B', 'C', 'D', 'E', 'F' };
227     /**
228      * Convert a byte array to a hexadecimal string.
229      */
toHexString(byte[] array, int offset, int length)230     public static String toHexString(byte[] array, int offset, int length) {
231         char[] buf = new char[length * 2];
232 
233         int bufIndex = 0;
234         for (int i = offset; i < offset + length; i++) {
235             byte b = array[i];
236             buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
237             buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
238         }
239 
240         return new String(buf);
241     }
242 }
243