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