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_NEWPREFIX = 52; 127 public static final short RTM_NEWNDUSEROPT = 68; 128 129 // Netfilter netlink message types are presented by two bytes: high byte subsystem and 130 // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in 131 // include/uapi/linux/netfilter/nfnetlink.h 132 public static final short NFNL_SUBSYS_CTNETLINK = 1; 133 134 public static final short IPCTNL_MSG_CT_NEW = 0; 135 public static final short IPCTNL_MSG_CT_GET = 1; 136 public static final short IPCTNL_MSG_CT_DELETE = 2; 137 public static final short IPCTNL_MSG_CT_GET_CTRZERO = 3; 138 public static final short IPCTNL_MSG_CT_GET_STATS_CPU = 4; 139 public static final short IPCTNL_MSG_CT_GET_STATS = 5; 140 public static final short IPCTNL_MSG_CT_GET_DYING = 6; 141 public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7; 142 143 /* see include/uapi/linux/sock_diag.h */ 144 public static final short SOCK_DIAG_BY_FAMILY = 20; 145 public static final short SOCK_DESTROY = 21; 146 147 // Netlink groups. 148 public static final int RTMGRP_LINK = 1; 149 public static final int RTMGRP_IPV4_IFADDR = 0x10; 150 public static final int RTMGRP_IPV6_IFADDR = 0x100; 151 public static final int RTMGRP_IPV6_ROUTE = 0x400; 152 public static final int RTNLGRP_IPV6_PREFIX = 18; 153 public static final int RTMGRP_IPV6_PREFIX = 1 << (RTNLGRP_IPV6_PREFIX - 1); 154 public static final int RTNLGRP_ND_USEROPT = 20; 155 public static final int RTMGRP_ND_USEROPT = 1 << (RTNLGRP_ND_USEROPT - 1); 156 157 // Netlink family 158 public static final short RTNL_FAMILY_IP6MR = 129; 159 160 // Device flags. 161 public static final int IFF_UP = 1 << 0; 162 public static final int IFF_LOWER_UP = 1 << 16; 163 164 // Known values for struct rtmsg rtm_protocol. 165 public static final short RTPROT_KERNEL = 2; 166 public static final short RTPROT_RA = 9; 167 168 // Known values for struct rtmsg rtm_scope. 169 public static final short RT_SCOPE_UNIVERSE = 0; 170 171 // Known values for struct rtmsg rtm_type. 172 public static final short RTN_UNICAST = 1; 173 174 // Known values for struct rtmsg rtm_flags. 175 public static final int RTM_F_CLONED = 0x200; 176 177 /** 178 * Convert a netlink message type to a string for control message. 179 */ 180 @NonNull stringForCtlMsgType(short nlmType)181 private static String stringForCtlMsgType(short nlmType) { 182 switch (nlmType) { 183 case NLMSG_NOOP: return "NLMSG_NOOP"; 184 case NLMSG_ERROR: return "NLMSG_ERROR"; 185 case NLMSG_DONE: return "NLMSG_DONE"; 186 case NLMSG_OVERRUN: return "NLMSG_OVERRUN"; 187 default: return "unknown control message type: " + String.valueOf(nlmType); 188 } 189 } 190 191 /** 192 * Convert a netlink message type to a string for NETLINK_ROUTE. 193 */ 194 @NonNull stringForRtMsgType(short nlmType)195 private static String stringForRtMsgType(short nlmType) { 196 switch (nlmType) { 197 case RTM_NEWLINK: return "RTM_NEWLINK"; 198 case RTM_DELLINK: return "RTM_DELLINK"; 199 case RTM_GETLINK: return "RTM_GETLINK"; 200 case RTM_SETLINK: return "RTM_SETLINK"; 201 case RTM_NEWADDR: return "RTM_NEWADDR"; 202 case RTM_DELADDR: return "RTM_DELADDR"; 203 case RTM_GETADDR: return "RTM_GETADDR"; 204 case RTM_NEWROUTE: return "RTM_NEWROUTE"; 205 case RTM_DELROUTE: return "RTM_DELROUTE"; 206 case RTM_GETROUTE: return "RTM_GETROUTE"; 207 case RTM_NEWNEIGH: return "RTM_NEWNEIGH"; 208 case RTM_DELNEIGH: return "RTM_DELNEIGH"; 209 case RTM_GETNEIGH: return "RTM_GETNEIGH"; 210 case RTM_NEWRULE: return "RTM_NEWRULE"; 211 case RTM_DELRULE: return "RTM_DELRULE"; 212 case RTM_GETRULE: return "RTM_GETRULE"; 213 case RTM_NEWPREFIX: return "RTM_NEWPREFIX"; 214 case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT"; 215 default: return "unknown RTM type: " + String.valueOf(nlmType); 216 } 217 } 218 219 /** 220 * Convert a netlink message type to a string for NETLINK_INET_DIAG. 221 */ 222 @NonNull stringForInetDiagMsgType(short nlmType)223 private static String stringForInetDiagMsgType(short nlmType) { 224 switch (nlmType) { 225 case SOCK_DIAG_BY_FAMILY: return "SOCK_DIAG_BY_FAMILY"; 226 default: return "unknown SOCK_DIAG type: " + String.valueOf(nlmType); 227 } 228 } 229 230 /** 231 * Convert a netlink message type to a string for NETLINK_NETFILTER. 232 */ 233 @NonNull stringForNfMsgType(short nlmType)234 private static String stringForNfMsgType(short nlmType) { 235 final byte subsysId = (byte) (nlmType >> 8); 236 final byte msgType = (byte) nlmType; 237 switch (subsysId) { 238 case NFNL_SUBSYS_CTNETLINK: 239 switch (msgType) { 240 case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW"; 241 case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET"; 242 case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE"; 243 case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO"; 244 case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU"; 245 case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS"; 246 case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING"; 247 case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED"; 248 } 249 break; 250 } 251 return "unknown NETFILTER type: " + String.valueOf(nlmType); 252 } 253 254 /** 255 * Convert a netlink message type to a string by netlink family. 256 */ 257 @NonNull stringForNlMsgType(short nlmType, int nlFamily)258 public static String stringForNlMsgType(short nlmType, int nlFamily) { 259 // Reserved control messages. The netlink family is ignored. 260 // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h. 261 if (nlmType <= NLMSG_MAX_RESERVED) return stringForCtlMsgType(nlmType); 262 263 // Netlink family messages. The netlink family is required. Note that the reason for using 264 // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are 265 // not constant. 266 if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType); 267 if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType); 268 if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType); 269 270 return "unknown type: " + String.valueOf(nlmType); 271 } 272 273 private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 274 'A', 'B', 'C', 'D', 'E', 'F' }; 275 /** 276 * Convert a byte array to a hexadecimal string. 277 */ toHexString(byte[] array, int offset, int length)278 public static String toHexString(byte[] array, int offset, int length) { 279 char[] buf = new char[length * 2]; 280 281 int bufIndex = 0; 282 for (int i = offset; i < offset + length; i++) { 283 byte b = array[i]; 284 buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; 285 buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; 286 } 287 288 return new String(buf); 289 } 290 } 291