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