├── .gitignore ├── License.txt ├── README.md ├── demo └── main.cpp ├── docs └── protocol.md ├── include └── NetworkStatisticsClient.hpp ├── libntstat.xcodeproj └── project.pbxproj ├── replay └── main.cpp └── src ├── NTStatKernelStructHandler.hpp ├── NetworkStatisticsClientImpl.cpp ├── ntstat_kernel_2050.h ├── ntstat_kernel_2422.cpp ├── ntstat_kernel_2422.h ├── ntstat_kernel_2782.cpp ├── ntstat_kernel_2782.h ├── ntstat_kernel_3248.cpp ├── ntstat_kernel_3248.h ├── ntstat_kernel_3789.cpp ├── ntstat_kernel_3789.h ├── ntstat_kernel_4570.cpp └── ntstat_kernel_4570.h /.gitignore: -------------------------------------------------------------------------------- 1 | libntstat.xcodeproj/project.xcworkspace 2 | libntstat.xcodeproj/xcuserdata 3 | /build 4 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | https://github.com/packetzero/libntstat 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (C) 2017 Alex Malone 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## C++ library to receive network stats on MacOS (XNU Darwin) 2 | 3 | ## NOTE: A user (Sunil-P) reported that the socket used is gone in Big Sur, so this method will not work. 4 | 5 | ### Introduction 6 | 7 | Darwin kernel provides an unpublished API to receive pseudo realtime notifications of network connections and stats. This is the same data that powers Activity Monitor. See [protocol.md](./docs/protocol.md) for details on the underlying mechanism and protocol. Feature summary: 8 | 9 | - Receive Add, Stats, Remove on every TCP connection 10 | - Gather cumulative network stats by process 11 | - cannot UDP conversations. Data only provides local port, no addresses 12 | 13 | ### Usage 14 | 15 | The application implements the NetworkStatisticsListener interface (C++ pure virtual class), then creates a NetworkStatisticsClient instance, connects it to the kernel, optionally call configure(), and calls run() from a dedicated thread. The interface is simple and has the following methods. See [NetworkStatisticsClient.hpp](./include/NetworkStatisticsClient.hpp) for details. 16 | 17 | - onStreamAdded() 18 | - onStreamRemoved() 19 | - onStreamStatsUpdate() 20 | 21 | ### Demo Application 22 | There is a command-line application called 'demo' that prints simple network stream information to stdout. Example output: 23 | ``` 24 | XNU version:3789 25 | + 15:23:27 TCP 10.0.20.179 58760 - 52.86.2.3 443 pid:66 (epagd) 26 | + 15:23:27 TCP 10.0.20.179 58718 - 17.249.60.9 5223 pid:83 (apsd) 27 | @+ 15:23:28 pid:399 (mongod) LISTEN TCP port:27017 28 | @+ 15:23:28 pid:1 (launchd) LISTEN TCP port:22 29 | + 15:23:54 TCP 10.0.20.179 61608 - 172.217.9.170 443 pid:668 (com.apple.Safari) 30 | + 15:23:54 TCP 10.0.20.179 61609 - 17.249.219.246 443 pid:353 (nsurlsessiond) 31 | + 15:23:54 TCP 10.0.20.179 61610 - 72.247.204.12 443 pid:18175 (com.apple.WebKit) 32 | + 15:23:54 TCP 10.0.20.179 61611 - 13.33.115.210 443 pid:18175 (com.apple.WebKit) 33 | + 15:23:55 TCP 10.0.20.179 61612 - 13.33.115.210 443 pid:18175 (com.apple.WebKit) 34 | + 15:23:55 TCP fdd4:69cc:c669:be20::1d4c 61615 - 2607:f8b0:4000:814::200e 443 pid:18175 (com.apple.WebKit) 35 | - 15:23:55 TCP fdd4:69cc:c669:be20::1d4c 61615 - 2607:f8b0:4000:814::200e 443 pid:18175 (com.apple.WebKit) FAILED 36 | - 15:23:56 TCP 10.0.20.179 61609 - 17.249.219.246 443 pid:353 (nsurlsessiond) 37 | bytes (tx/rx):2181/3269 packets:6/5 wifi 38 | # 15:24:22 TCP 10.0.20.179 58718 - 17.249.60.9 5223 pid:83 (apsd) 39 | bytes (tx/rx):3956/4924 packets:27/28 wifi 40 | # 15:24:22 TCP 10.0.20.179 58760 - 52.86.2.3 443 pid:66 (epagd) 41 | bytes (tx/rx):926/17047 packets:5/314 wifi 42 | ``` 43 | 44 | ### Credits 45 | This is based on lsock by Jonathan Levin (http://newosxbook.com/index.php?page=code). There were several significant changes to the socket protocol in 10.12 Sierra (XNU v3789) that breaks lsock. He said that an update to lsock is coming soon. 46 | -------------------------------------------------------------------------------- /demo/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // libntstat demo 3 | // 4 | // Copyright © 2017 Alex Malone. All rights reserved. 5 | 6 | #include "../include/NetworkStatisticsClient.hpp" 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | string stream2text (const NTStatStreamKey& s); 13 | string timestr(); 14 | std::string stateToText(const NTStatStream *stream); 15 | 16 | /* 17 | * Implementing this listener allows receipt of events. 18 | */ 19 | class MyNetstatListener : public NetworkStatisticsListener 20 | { 21 | virtual void onStreamAdded(const NTStatStream *stream) 22 | { 23 | log(stream, '+'); 24 | } 25 | virtual void onStreamRemoved(const NTStatStream *stream) 26 | { 27 | log(stream, '-'); 28 | } 29 | virtual void onStreamStatsUpdate(const NTStatStream *stream) 30 | { 31 | log(stream, '#'); 32 | } 33 | 34 | 35 | void log(const NTStatStream* stream, char displayChar) 36 | { 37 | if (IS_LISTEN_PORT(stream)) 38 | { 39 | printf(" @%c %s pid:%u (%s) LISTEN %s port:%u\n", displayChar, timestr().c_str(), stream->process.pid, 40 | stream->process.name,(stream->key.ipproto == IPPROTO_TCP ? "TCP" : "UDP"), ntohs(stream->key.lport)); 41 | } 42 | else 43 | { 44 | //string stateStr = (displayChar == '-' ? stateToText(stream) : ""); 45 | string notes = ""; 46 | if (displayChar == '-' && stream->key.ipproto == IPPROTO_TCP && 47 | stream->stats.rxpackets == 0) notes = "FAILED"; 48 | 49 | printf(" %c %s %s pid:%u (%s) %s id:%llu\n", displayChar, timestr().c_str(), 50 | stream2text(stream->key).c_str(), stream->process.pid, stream->process.name, notes.c_str(), stream->id); 51 | 52 | // write bytes if present on update/remove 53 | 54 | string medium = "wired"; 55 | if (stream->stats.cell_txbytes > 0) medium = "cell"; 56 | if (stream->stats.wifi_txbytes > 0) medium = "wifi"; 57 | 58 | if (displayChar != '+' && (stream->stats.rxpackets > 0 || stream->stats.txpackets > 0)) 59 | printf(" bytes (tx/rx):%llu/%llu packets:%llu/%llu %s\n",stream->stats.txbytes, stream->stats.rxbytes, stream->stats.txpackets, stream->stats.rxpackets, medium.c_str()); 60 | } 61 | } 62 | 63 | }; 64 | 65 | int main(int argc, const char * argv[]) 66 | { 67 | // create 68 | 69 | MyNetstatListener listener = MyNetstatListener(); 70 | NetworkStatisticsClient* netstatClient = NetworkStatisticsClientNew(&listener); 71 | 72 | // connect to ntstat via kernel control module socket 73 | 74 | if (false == netstatClient->connectToKernel()) { 75 | printf("Failed to establish network.statistics system control socket\n"); 76 | return 2; 77 | } 78 | 79 | // configure 80 | bool wantTcp=true, wantUdp=false; 81 | uint32_t updateIntervalSeconds = 60; 82 | netstatClient->configure(wantTcp, wantUdp, updateIntervalSeconds); 83 | 84 | // in a real app, we would want to run this in a dedicated thread 85 | netstatClient->run(); 86 | 87 | return 0; 88 | } 89 | 90 | // ==================== helper functions ====================== 91 | 92 | #include 93 | 94 | string addr2text ( const in_addr& Addr ) 95 | { 96 | char IPv4AddressAsString[INET_ADDRSTRLEN]; //buffer needs 16 characters min 97 | if ( NULL != inet_ntop ( AF_INET, &Addr, IPv4AddressAsString, sizeof(IPv4AddressAsString) ) ) 98 | return string(IPv4AddressAsString); 99 | return "?"; 100 | } 101 | 102 | string addr2text ( const in6_addr& Addr ) 103 | { 104 | char IPv6AddressAsString[INET6_ADDRSTRLEN]; //buffer needs 46 characters min 105 | if ( NULL != inet_ntop ( AF_INET6, &Addr, IPv6AddressAsString, sizeof(IPv6AddressAsString) ) ) 106 | return string(IPv6AddressAsString); 107 | return "?"; 108 | } 109 | 110 | string stream2text (const NTStatStreamKey& s) 111 | { 112 | char tmp[256]; 113 | string val = s.ipproto == IPPROTO_TCP ? "TCP " : "UDP "; 114 | if (s.isV6) 115 | { 116 | val += addr2text(s.local.addr6); 117 | sprintf(tmp," %d - ", ntohs(s.lport)); 118 | val += tmp; 119 | val += addr2text(s.remote.addr6); 120 | sprintf(tmp," %d", ntohs(s.rport)); 121 | val += tmp; 122 | } else { 123 | val += addr2text(s.local.addr4); 124 | sprintf(tmp," %d - ", ntohs(s.lport)); 125 | val += tmp; 126 | val += addr2text(s.remote.addr4); 127 | sprintf(tmp," %d", ntohs(s.rport)); 128 | val += tmp; 129 | } 130 | return val; 131 | } 132 | 133 | std::string stateToText(const NTStatStream *stream) 134 | { 135 | switch(stream->states.state) 136 | { 137 | case TCPS_CLOSED: return ("CLOSED"); 138 | case TCPS_LISTEN: return ("LISTENING"); 139 | case TCPS_ESTABLISHED: return ("ESTABLISHED"); 140 | case TCPS_CLOSING: return ("CLOSING"); 141 | case TCPS_SYN_SENT: return ("SYN_SENT"); 142 | case TCPS_LAST_ACK: return ("LAST_ACK"); 143 | case TCPS_CLOSE_WAIT: return ("CLOSE_WAIT"); 144 | case TCPS_TIME_WAIT: return ("TIME_WAIT"); 145 | case TCPS_FIN_WAIT_1 : return ("FIN_WAIT_1"); 146 | case TCPS_FIN_WAIT_2 : return ("FIN_WAIT_2"); 147 | 148 | default: 149 | return("?"); 150 | } 151 | 152 | } // stateToText 153 | 154 | #include 155 | string timestr() 156 | { 157 | char timestamp[64]=""; 158 | time_t now = time(NULL); 159 | struct tm *tm = localtime(&now); 160 | strftime(timestamp, 63, "%H:%M:%S", tm); 161 | return string(timestamp); 162 | } 163 | -------------------------------------------------------------------------------- /docs/protocol.md: -------------------------------------------------------------------------------- 1 | # Darwin "network.statistics" Binary API 2 | 3 | This document gives an overview of the API that can be used by applications to receive network stream data from the Darwin kernel. The NetworkStatistics private framework library used by *Activity Monitor* application uses this API. The API is accessible via a [kernel control socket](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html), and currently does not require elevated privilege. 4 | 5 | **NOTE: This API is undocumented. Applications leveraging this API will have to anticipate and adapt to breaking changes in each major kernel release.** 6 | 7 | **NOTE: Domain names are not part of the API, only IP Addresses**. 8 | 9 | ### Terminology 10 | 11 | **Source** A source is a bi-directional TCP connection, or uni-directional UDP flow. The kernel assigns a unique srcRef to each source. The srcRef datatype changed from uin32_t to uint64_t in XNU version 3789 (Sierra). 12 | 13 | ### Struct header 14 | Each request and response message is a struct that starts with the following header. The *context* field is used by the application to match response messages to the request message. The *type* field needs to be one of the *NSTAT_MSG_TYPE_* enum values. The *length* field should match the length of the request or response message struct. The kernel (and application) can use this as a versioning check, as some message structs have different size across kernel versions. 15 | 16 | ``` 17 | typedef struct nstat_msg_hdr 18 | { 19 | u_int64_t context; 20 | u_int32_t type; 21 | u_int16_t length; 22 | u_int16_t flags; 23 | } nstat_msg_hdr; 24 | ``` 25 | 26 | ## Request Types 27 | - **NSTAT_MSG_TYPE_ADD_SRC** Add a specific source. 28 | - **NSTAT_MSG_TYPE_ADD_ALL_SRCS** Subscribe to all sources for a specific provider (TCP, UDP, etc). 29 | - **NSTAT_MSG_TYPE_REM_SRC** Unsubscribe from a source. 30 | - **NSTAT_MSG_TYPE_QUERY_SRC** Request SRC_COUNTS for a specific source or all active sources. 31 | - **NSTAT_MSG_TYPE_GET_SRC_DESC** Request details (addresses and ports) for all a specific source. 32 | 33 | ## Response Types 34 | - **NSTAT_MSG_TYPE_SUCCESS** Last response message for a request, indicating success. 35 | - **NSTAT_MSG_TYPE_SRC_ADDED** After successfully subscribing to sources (via ADD_SRC or ADD_ALL_SRC), the application will receive *SRC_ADDED* messages for new sources. The message is not very informative. It consists simply of the header, providerId, and srcRef. To get the stream details, the application must send a GET_SRC_DESC message for it. 36 | - **NSTAT_MSG_TYPE_SRC_REMOVED** When the kernel has determined that a source is finished (e.g. TCP connection terminated), the application will receive a *SRC_REMOVED* message for it. 37 | - **NSTAT_MSG_TYPE_SRC_DESC** Provides details about a source, such as local and remote address and layer-4 ports, interface (en0, etc.), process ID, and abbreviated process name. 38 | - **NSTAT_MSG_TYPE_SRC_COUNTS** Prior to a *SRC_REMOVED* message, a SRC_COUNTS will be received to summarize the packets and bytes transmitted and received. If the application wants to receive an update on persistent connections, it must send a *QUERY_SRC* request message. In addition to the total counters, there are counters broken down by medium: wifi, wired, and cellular. Note that prior to XNU version 3789, the *wired* counters were not specified. 39 | - **NSTAT_MSG_TYPE_ERROR** Direct response to a request message, indicating error. The response message struct has an *errno.h* error code. To determine the request that was the cause of the failure, the application needs to keep track of request messages and lookup request message with matching *context* field. Examples of common errors: Trying to ADD_ALL_SRC with invalid providerId will yield ENOENT error. Requesting GET_SRC_DESC or QUERY_SRC for a source that has already been reported with a SRC_REMOVED message. If your application is not keeping up with reading the response messages, the buffer is full, and the kernel cannot write any more messages. This cause an ERROR message with ENOBUFS error code. 40 | 41 | ## Kernel Control Socket 42 | 43 | If you run the command `netstat -a` from a command-prompt, you will see something similar to the following in the output. The **com.apple.network.statistics** name is the one we are interested in. In this example, there are 6 active socket connections established by applications. We can see that the receive buffer size is 8192 bytes, while the output buffer size is 2048 bytes. This is from the viewpoint of the application, so the kernel can only write 2KB of response messages. Typically, the application receives SRC_ADDED, SRC_COUNTS, SRC_DESC, SRC_REMOVED for each source (e.g. network connection). On Sierra and later, this is about 492 bytes for just one observed connection. Therefore, the chances of dropping some data under heavy network activity is likely. 44 | ``` 45 | Registered kernel control modules 46 | id flags pcbcount rcvbuf sndbuf name 47 | 3 9 0 524288 524288 com.apple.content-filter 48 | 6 1 12 65536 65536 com.apple.net.netagent 49 | 9 0 32 8192 2048 com.apple.netsrc 50 | a 18 6 8192 2048 com.apple.network.statistics 51 | .. 52 | Active kernel control sockets 53 | Proto Recv-Q Send-Q unit id name 54 | .. 55 | kctl 0 0 1 10 com.apple.network.statistics 56 | kctl 0 0 2 10 com.apple.network.statistics 57 | kctl 0 0 3 10 com.apple.network.statistics 58 | kctl 0 0 4 10 com.apple.network.statistics 59 | kctl 0 0 5 10 com.apple.network.statistics 60 | kctl 0 0 8 10 com.apple.network.statistics 61 | ``` 62 | -------------------------------------------------------------------------------- /include/NetworkStatisticsClient.hpp: -------------------------------------------------------------------------------- 1 | // NetworkStatisticsClient.hpp 2 | // Copyright © 2017 Alex Malone. All rights reserved. 3 | 4 | #ifndef NetworkStatisticsClient_hpp 5 | #define NetworkStatisticsClient_hpp 6 | 7 | #include 8 | #include 9 | 10 | struct NTStatStream; 11 | 12 | /* 13 | * NetworkStatisticsListener 14 | * 15 | * Applications need to implement this interface to receive callbacks 16 | * from the NetworkStatisticsClient. 17 | * 18 | * Note: Darwin reports bidirectional UDP conversations as two separate streams 19 | * 20 | */ 21 | class NetworkStatisticsListener 22 | { 23 | public: 24 | virtual void onStreamAdded(const NTStatStream *stream)=0; 25 | 26 | virtual void onStreamRemoved(const NTStatStream *stream)=0; 27 | 28 | virtual void onStreamStatsUpdate(const NTStatStream *stream)=0; 29 | }; 30 | 31 | // this is for testing... you can ignore 32 | class NTStatClientEmulation 33 | { 34 | public: 35 | // saves all messages (requests and responses) to "./ntstat-xnu-.bin" 36 | virtual void enableRecording() = 0; 37 | 38 | // in the place of run(), this will process messages from filename 39 | virtual void runRecording(char *filename, unsigned int xnuVersion) = 0; 40 | }; 41 | 42 | const int NTSTAT_LOGF_ERROR = (1 << 1); 43 | const int NTSTAT_LOGF_SENDRECV = (1 << 2); 44 | const int NTSTAT_LOGF_DEBUG = (1 << 3); 45 | const int NTSTAT_LOGF_TRACE = (1 << 4); 46 | const int NTSTAT_LOGF_DROPS = (1 << 5); 47 | 48 | /* 49 | * NetworkStatisticsClient 50 | * 51 | * This is the interface to interact with the com.apple.network.statistics data. 52 | * Behind the scenes, the implementation creates a system socket, subscribes 53 | * to TCP and UDP sources, and passes along the data to the listener. 54 | */ 55 | class NetworkStatisticsClient : public NTStatClientEmulation 56 | { 57 | public: 58 | /* 59 | * This should be done before call to run(). 60 | */ 61 | virtual bool connectToKernel() = 0; 62 | 63 | /* 64 | * returns true if connectToKernel() was called and was successful. 65 | */ 66 | virtual bool isConnected() = 0; 67 | 68 | /* 69 | * Blocking: run from dedicated thread. Subscribes to TCP/UDP and continuously reads messages. 70 | * The connection to the kernel will be disconnected when run() exits. 71 | */ 72 | virtual void run() = 0; 73 | 74 | /* 75 | * configure() - needs to be called prior to run() 76 | * 77 | * @param wantTcp If true, include TCP streams. Default: true. 78 | * @param wantUdp If true, include UDP streams. Default: false. 79 | * @param updateIntervalSeconds Interval in seconds to receive stat updates on persistent 80 | * connections. If zero, this feature is turned off. Default: 30. 81 | */ 82 | virtual void configure(bool wantTcp, bool wantUdp, uint32_t updateIntervalSeconds) = 0; 83 | 84 | /* 85 | * Will set the stop flag, so run() will exit. 86 | */ 87 | virtual void stop() = 0; 88 | 89 | /* 90 | * configure logging. Default flags == 0, no logging. 91 | */ 92 | virtual void setLogging(uint8_t flags) = 0; 93 | 94 | /* 95 | * returns the number of ENOBUFS errors received from kernel, indicating 96 | * the inability to send some requested information due to full buffer. 97 | * See docs/protocol.md for more details. 98 | */ 99 | virtual uint32_t getNumDrops() = 0; 100 | 101 | }; 102 | 103 | // Instantiate (singleton) the NetworkStatisticsClient 104 | 105 | NetworkStatisticsClient* NetworkStatisticsClientNew(NetworkStatisticsListener* l); 106 | 107 | // Data types for reporting 108 | 109 | typedef union { 110 | struct in_addr addr4; 111 | struct in6_addr addr6; 112 | } addr_t; 113 | 114 | struct NTStatCounters 115 | { 116 | uint64_t rxpackets; // failed if TCP && rxpackets == 0 && txpackets > 0 117 | uint64_t txpackets; 118 | uint64_t rxbytes; 119 | uint64_t txbytes; 120 | 121 | uint64_t cell_rxbytes; 122 | uint64_t cell_txbytes; 123 | uint64_t wifi_rxbytes; 124 | uint64_t wifi_txbytes; 125 | uint64_t wired_rxbytes; // wnot present for XNU v2422 and earlier 126 | uint64_t wired_txbytes; 127 | }; 128 | 129 | struct NTStatStreamState 130 | { 131 | uint32_t state; // TCPS_LISTEN, TCPS_SYN_SENT, etc. 132 | uint32_t txcwindow; // TCP only 133 | uint32_t txwindow; // TCP only 134 | }; 135 | 136 | struct NTStatStreamKey 137 | { 138 | uint8_t isV6; 139 | uint8_t ipproto; // IPPROTO_TCP or IPPROTO_UDP 140 | uint16_t pad; 141 | uint32_t ifindex; 142 | uint16_t lport; // local port (network-endian) 143 | uint16_t rport; // remove port (network-endian) 144 | addr_t local; 145 | addr_t remote; 146 | 147 | bool operator<(const NTStatStreamKey& b) const; // needed to be a key type for std::map 148 | }; 149 | 150 | struct NTStatProcess 151 | { 152 | uint32_t pid; 153 | char name[64]; 154 | }; 155 | 156 | struct NTStatStream 157 | { 158 | // these are constant once we see the stream 159 | uint64_t id; // Stream ID provided by kernel. Unique for app runtime. Can rollover at uint32_t, so id can be reused. 160 | NTStatStreamKey key; 161 | NTStatProcess process; 162 | 163 | // these get updated 164 | NTStatCounters stats; 165 | NTStatStreamState states; 166 | 167 | }; 168 | 169 | /* 170 | #include 171 | struct NTStatInterface 172 | { 173 | std::string name; 174 | uint32_t ifindex; 175 | uint64_t threshold; 176 | unsigned int type; 177 | std::string description; 178 | }; 179 | */ 180 | 181 | // convenience macros 182 | 183 | #define IS_LISTEN_PORT(pstream) (0 == (pstream)->key.rport) 184 | 185 | #endif /* NetworkStatisticsClient_hpp */ 186 | -------------------------------------------------------------------------------- /libntstat.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 05313D141FD9A99E006FB69A /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05313D131FD9A99E006FB69A /* main.cpp */; }; 11 | 05313D1F1FD9CDFC006FB69A /* libntstat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 05C21B361FD9A59000DDAC9B /* libntstat.a */; }; 12 | 05313D211FD9D3F2006FB69A /* ntstat_kernel_3789.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05313D201FD9D3F2006FB69A /* ntstat_kernel_3789.cpp */; }; 13 | 05313D2B1FD9F5A5006FB69A /* ntstat_kernel_3248.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05313D221FD9F5A3006FB69A /* ntstat_kernel_3248.cpp */; }; 14 | 05313D2C1FD9F5A5006FB69A /* ntstat_kernel_3789.h in Headers */ = {isa = PBXBuildFile; fileRef = 05313D231FD9F5A4006FB69A /* ntstat_kernel_3789.h */; }; 15 | 05313D2D1FD9F5A5006FB69A /* ntstat_kernel_2782.h in Headers */ = {isa = PBXBuildFile; fileRef = 05313D241FD9F5A4006FB69A /* ntstat_kernel_2782.h */; }; 16 | 05313D2E1FD9F5A5006FB69A /* ntstat_kernel_2422.h in Headers */ = {isa = PBXBuildFile; fileRef = 05313D251FD9F5A4006FB69A /* ntstat_kernel_2422.h */; }; 17 | 05313D2F1FD9F5A5006FB69A /* ntstat_kernel_4570.h in Headers */ = {isa = PBXBuildFile; fileRef = 05313D261FD9F5A4006FB69A /* ntstat_kernel_4570.h */; }; 18 | 05313D301FD9F5A5006FB69A /* ntstat_kernel_3248.h in Headers */ = {isa = PBXBuildFile; fileRef = 05313D271FD9F5A4006FB69A /* ntstat_kernel_3248.h */; }; 19 | 05313D311FD9F5A5006FB69A /* ntstat_kernel_4570.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05313D281FD9F5A4006FB69A /* ntstat_kernel_4570.cpp */; }; 20 | 05313D321FD9F5A5006FB69A /* ntstat_kernel_2050.h in Headers */ = {isa = PBXBuildFile; fileRef = 05313D291FD9F5A5006FB69A /* ntstat_kernel_2050.h */; }; 21 | 05313D361FD9F7AB006FB69A /* ntstat_kernel_2782.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05313D341FD9F7AB006FB69A /* ntstat_kernel_2782.cpp */; }; 22 | 05313D371FD9F7AB006FB69A /* ntstat_kernel_2422.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05313D351FD9F7AB006FB69A /* ntstat_kernel_2422.cpp */; }; 23 | 05313D391FDA051F006FB69A /* NetworkStatisticsClientImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05313D381FDA051F006FB69A /* NetworkStatisticsClientImpl.cpp */; }; 24 | 05313D3B1FDA0E2E006FB69A /* NTStatKernelStructHandler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 05313D3A1FDA0E2D006FB69A /* NTStatKernelStructHandler.hpp */; }; 25 | 059BEC771FE30C0F00E4879A /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 059BEC761FE30C0F00E4879A /* main.cpp */; }; 26 | 059BEC7B1FE30CCB00E4879A /* libntstat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 05C21B361FD9A59000DDAC9B /* libntstat.a */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 05313D181FD9AEEE006FB69A /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 05C21B2E1FD9A59000DDAC9B /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 05C21B351FD9A59000DDAC9B; 35 | remoteInfo = libntstat; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXCopyFilesBuildPhase section */ 40 | 05313D0F1FD9A99E006FB69A /* CopyFiles */ = { 41 | isa = PBXCopyFilesBuildPhase; 42 | buildActionMask = 2147483647; 43 | dstPath = /usr/share/man/man1/; 44 | dstSubfolderSpec = 0; 45 | files = ( 46 | ); 47 | runOnlyForDeploymentPostprocessing = 1; 48 | }; 49 | 059BEC721FE30C0F00E4879A /* CopyFiles */ = { 50 | isa = PBXCopyFilesBuildPhase; 51 | buildActionMask = 2147483647; 52 | dstPath = /usr/share/man/man1/; 53 | dstSubfolderSpec = 0; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 1; 57 | }; 58 | /* End PBXCopyFilesBuildPhase section */ 59 | 60 | /* Begin PBXFileReference section */ 61 | 05313D0C1FD9A665006FB69A /* include */ = {isa = PBXFileReference; lastKnownFileType = folder; path = include; sourceTree = ""; }; 62 | 05313D111FD9A99E006FB69A /* demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = demo; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 05313D131FD9A99E006FB69A /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 64 | 05313D201FD9D3F2006FB69A /* ntstat_kernel_3789.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ntstat_kernel_3789.cpp; path = src/ntstat_kernel_3789.cpp; sourceTree = ""; }; 65 | 05313D221FD9F5A3006FB69A /* ntstat_kernel_3248.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ntstat_kernel_3248.cpp; path = src/ntstat_kernel_3248.cpp; sourceTree = ""; }; 66 | 05313D231FD9F5A4006FB69A /* ntstat_kernel_3789.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ntstat_kernel_3789.h; path = src/ntstat_kernel_3789.h; sourceTree = ""; }; 67 | 05313D241FD9F5A4006FB69A /* ntstat_kernel_2782.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ntstat_kernel_2782.h; path = src/ntstat_kernel_2782.h; sourceTree = ""; }; 68 | 05313D251FD9F5A4006FB69A /* ntstat_kernel_2422.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ntstat_kernel_2422.h; path = src/ntstat_kernel_2422.h; sourceTree = ""; }; 69 | 05313D261FD9F5A4006FB69A /* ntstat_kernel_4570.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ntstat_kernel_4570.h; path = src/ntstat_kernel_4570.h; sourceTree = ""; }; 70 | 05313D271FD9F5A4006FB69A /* ntstat_kernel_3248.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ntstat_kernel_3248.h; path = src/ntstat_kernel_3248.h; sourceTree = ""; }; 71 | 05313D281FD9F5A4006FB69A /* ntstat_kernel_4570.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ntstat_kernel_4570.cpp; path = src/ntstat_kernel_4570.cpp; sourceTree = ""; }; 72 | 05313D291FD9F5A5006FB69A /* ntstat_kernel_2050.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ntstat_kernel_2050.h; path = src/ntstat_kernel_2050.h; sourceTree = ""; }; 73 | 05313D341FD9F7AB006FB69A /* ntstat_kernel_2782.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ntstat_kernel_2782.cpp; path = src/ntstat_kernel_2782.cpp; sourceTree = ""; }; 74 | 05313D351FD9F7AB006FB69A /* ntstat_kernel_2422.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ntstat_kernel_2422.cpp; path = src/ntstat_kernel_2422.cpp; sourceTree = ""; }; 75 | 05313D381FDA051F006FB69A /* NetworkStatisticsClientImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkStatisticsClientImpl.cpp; path = src/NetworkStatisticsClientImpl.cpp; sourceTree = ""; }; 76 | 05313D3A1FDA0E2D006FB69A /* NTStatKernelStructHandler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = NTStatKernelStructHandler.hpp; path = src/NTStatKernelStructHandler.hpp; sourceTree = ""; }; 77 | 059BEC741FE30C0F00E4879A /* replay */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = replay; sourceTree = BUILT_PRODUCTS_DIR; }; 78 | 059BEC761FE30C0F00E4879A /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 79 | 05C21B361FD9A59000DDAC9B /* libntstat.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libntstat.a; sourceTree = BUILT_PRODUCTS_DIR; }; 80 | /* End PBXFileReference section */ 81 | 82 | /* Begin PBXFrameworksBuildPhase section */ 83 | 05313D0E1FD9A99E006FB69A /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | 05313D1F1FD9CDFC006FB69A /* libntstat.a in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | 059BEC711FE30C0F00E4879A /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | 059BEC7B1FE30CCB00E4879A /* libntstat.a in Frameworks */, 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | 05C21B331FD9A59000DDAC9B /* Frameworks */ = { 100 | isa = PBXFrameworksBuildPhase; 101 | buildActionMask = 2147483647; 102 | files = ( 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | /* End PBXFrameworksBuildPhase section */ 107 | 108 | /* Begin PBXGroup section */ 109 | 05313D121FD9A99E006FB69A /* demo */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 05313D131FD9A99E006FB69A /* main.cpp */, 113 | ); 114 | path = demo; 115 | sourceTree = ""; 116 | }; 117 | 05313D1A1FD9AEFC006FB69A /* Frameworks */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | ); 121 | name = Frameworks; 122 | sourceTree = ""; 123 | }; 124 | 059BEC751FE30C0F00E4879A /* replay */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 059BEC761FE30C0F00E4879A /* main.cpp */, 128 | ); 129 | path = replay; 130 | sourceTree = ""; 131 | }; 132 | 05C21B2D1FD9A59000DDAC9B = { 133 | isa = PBXGroup; 134 | children = ( 135 | 05313D3A1FDA0E2D006FB69A /* NTStatKernelStructHandler.hpp */, 136 | 05313D381FDA051F006FB69A /* NetworkStatisticsClientImpl.cpp */, 137 | 05313D351FD9F7AB006FB69A /* ntstat_kernel_2422.cpp */, 138 | 05313D341FD9F7AB006FB69A /* ntstat_kernel_2782.cpp */, 139 | 05313D291FD9F5A5006FB69A /* ntstat_kernel_2050.h */, 140 | 05313D251FD9F5A4006FB69A /* ntstat_kernel_2422.h */, 141 | 05313D241FD9F5A4006FB69A /* ntstat_kernel_2782.h */, 142 | 05313D221FD9F5A3006FB69A /* ntstat_kernel_3248.cpp */, 143 | 05313D271FD9F5A4006FB69A /* ntstat_kernel_3248.h */, 144 | 05313D231FD9F5A4006FB69A /* ntstat_kernel_3789.h */, 145 | 05313D281FD9F5A4006FB69A /* ntstat_kernel_4570.cpp */, 146 | 05313D261FD9F5A4006FB69A /* ntstat_kernel_4570.h */, 147 | 05313D201FD9D3F2006FB69A /* ntstat_kernel_3789.cpp */, 148 | 05313D0C1FD9A665006FB69A /* include */, 149 | 05313D121FD9A99E006FB69A /* demo */, 150 | 059BEC751FE30C0F00E4879A /* replay */, 151 | 05C21B371FD9A59000DDAC9B /* Products */, 152 | 05313D1A1FD9AEFC006FB69A /* Frameworks */, 153 | ); 154 | sourceTree = ""; 155 | }; 156 | 05C21B371FD9A59000DDAC9B /* Products */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 05C21B361FD9A59000DDAC9B /* libntstat.a */, 160 | 05313D111FD9A99E006FB69A /* demo */, 161 | 059BEC741FE30C0F00E4879A /* replay */, 162 | ); 163 | name = Products; 164 | sourceTree = ""; 165 | }; 166 | /* End PBXGroup section */ 167 | 168 | /* Begin PBXHeadersBuildPhase section */ 169 | 05C21B341FD9A59000DDAC9B /* Headers */ = { 170 | isa = PBXHeadersBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | 05313D301FD9F5A5006FB69A /* ntstat_kernel_3248.h in Headers */, 174 | 05313D2D1FD9F5A5006FB69A /* ntstat_kernel_2782.h in Headers */, 175 | 05313D2C1FD9F5A5006FB69A /* ntstat_kernel_3789.h in Headers */, 176 | 05313D2E1FD9F5A5006FB69A /* ntstat_kernel_2422.h in Headers */, 177 | 05313D3B1FDA0E2E006FB69A /* NTStatKernelStructHandler.hpp in Headers */, 178 | 05313D321FD9F5A5006FB69A /* ntstat_kernel_2050.h in Headers */, 179 | 05313D2F1FD9F5A5006FB69A /* ntstat_kernel_4570.h in Headers */, 180 | ); 181 | runOnlyForDeploymentPostprocessing = 0; 182 | }; 183 | /* End PBXHeadersBuildPhase section */ 184 | 185 | /* Begin PBXNativeTarget section */ 186 | 05313D101FD9A99E006FB69A /* demo */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = 05313D151FD9A99E006FB69A /* Build configuration list for PBXNativeTarget "demo" */; 189 | buildPhases = ( 190 | 05313D0D1FD9A99E006FB69A /* Sources */, 191 | 05313D0E1FD9A99E006FB69A /* Frameworks */, 192 | 05313D0F1FD9A99E006FB69A /* CopyFiles */, 193 | ); 194 | buildRules = ( 195 | ); 196 | dependencies = ( 197 | 05313D191FD9AEEE006FB69A /* PBXTargetDependency */, 198 | ); 199 | name = demo; 200 | productName = demo; 201 | productReference = 05313D111FD9A99E006FB69A /* demo */; 202 | productType = "com.apple.product-type.tool"; 203 | }; 204 | 059BEC731FE30C0F00E4879A /* replay */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 059BEC7A1FE30C0F00E4879A /* Build configuration list for PBXNativeTarget "replay" */; 207 | buildPhases = ( 208 | 059BEC701FE30C0F00E4879A /* Sources */, 209 | 059BEC711FE30C0F00E4879A /* Frameworks */, 210 | 059BEC721FE30C0F00E4879A /* CopyFiles */, 211 | ); 212 | buildRules = ( 213 | ); 214 | dependencies = ( 215 | ); 216 | name = replay; 217 | productName = replay; 218 | productReference = 059BEC741FE30C0F00E4879A /* replay */; 219 | productType = "com.apple.product-type.tool"; 220 | }; 221 | 05C21B351FD9A59000DDAC9B /* libntstat */ = { 222 | isa = PBXNativeTarget; 223 | buildConfigurationList = 05C21B411FD9A59000DDAC9B /* Build configuration list for PBXNativeTarget "libntstat" */; 224 | buildPhases = ( 225 | 05C21B321FD9A59000DDAC9B /* Sources */, 226 | 05C21B331FD9A59000DDAC9B /* Frameworks */, 227 | 05C21B341FD9A59000DDAC9B /* Headers */, 228 | ); 229 | buildRules = ( 230 | ); 231 | dependencies = ( 232 | ); 233 | name = libntstat; 234 | productName = libntstat; 235 | productReference = 05C21B361FD9A59000DDAC9B /* libntstat.a */; 236 | productType = "com.apple.product-type.library.static"; 237 | }; 238 | /* End PBXNativeTarget section */ 239 | 240 | /* Begin PBXProject section */ 241 | 05C21B2E1FD9A59000DDAC9B /* Project object */ = { 242 | isa = PBXProject; 243 | attributes = { 244 | LastUpgradeCheck = 0910; 245 | ORGANIZATIONNAME = AlexMalone; 246 | TargetAttributes = { 247 | 05313D101FD9A99E006FB69A = { 248 | CreatedOnToolsVersion = 9.1; 249 | ProvisioningStyle = Automatic; 250 | }; 251 | 059BEC731FE30C0F00E4879A = { 252 | CreatedOnToolsVersion = 9.2; 253 | ProvisioningStyle = Automatic; 254 | }; 255 | 05C21B351FD9A59000DDAC9B = { 256 | CreatedOnToolsVersion = 9.1; 257 | ProvisioningStyle = Automatic; 258 | }; 259 | }; 260 | }; 261 | buildConfigurationList = 05C21B311FD9A59000DDAC9B /* Build configuration list for PBXProject "libntstat" */; 262 | compatibilityVersion = "Xcode 8.0"; 263 | developmentRegion = en; 264 | hasScannedForEncodings = 0; 265 | knownRegions = ( 266 | en, 267 | ); 268 | mainGroup = 05C21B2D1FD9A59000DDAC9B; 269 | productRefGroup = 05C21B371FD9A59000DDAC9B /* Products */; 270 | projectDirPath = ""; 271 | projectRoot = ""; 272 | targets = ( 273 | 05C21B351FD9A59000DDAC9B /* libntstat */, 274 | 05313D101FD9A99E006FB69A /* demo */, 275 | 059BEC731FE30C0F00E4879A /* replay */, 276 | ); 277 | }; 278 | /* End PBXProject section */ 279 | 280 | /* Begin PBXSourcesBuildPhase section */ 281 | 05313D0D1FD9A99E006FB69A /* Sources */ = { 282 | isa = PBXSourcesBuildPhase; 283 | buildActionMask = 2147483647; 284 | files = ( 285 | 05313D141FD9A99E006FB69A /* main.cpp in Sources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | 059BEC701FE30C0F00E4879A /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | 059BEC771FE30C0F00E4879A /* main.cpp in Sources */, 294 | ); 295 | runOnlyForDeploymentPostprocessing = 0; 296 | }; 297 | 05C21B321FD9A59000DDAC9B /* Sources */ = { 298 | isa = PBXSourcesBuildPhase; 299 | buildActionMask = 2147483647; 300 | files = ( 301 | 05313D391FDA051F006FB69A /* NetworkStatisticsClientImpl.cpp in Sources */, 302 | 05313D371FD9F7AB006FB69A /* ntstat_kernel_2422.cpp in Sources */, 303 | 05313D361FD9F7AB006FB69A /* ntstat_kernel_2782.cpp in Sources */, 304 | 05313D311FD9F5A5006FB69A /* ntstat_kernel_4570.cpp in Sources */, 305 | 05313D211FD9D3F2006FB69A /* ntstat_kernel_3789.cpp in Sources */, 306 | 05313D2B1FD9F5A5006FB69A /* ntstat_kernel_3248.cpp in Sources */, 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | /* End PBXSourcesBuildPhase section */ 311 | 312 | /* Begin PBXTargetDependency section */ 313 | 05313D191FD9AEEE006FB69A /* PBXTargetDependency */ = { 314 | isa = PBXTargetDependency; 315 | target = 05C21B351FD9A59000DDAC9B /* libntstat */; 316 | targetProxy = 05313D181FD9AEEE006FB69A /* PBXContainerItemProxy */; 317 | }; 318 | /* End PBXTargetDependency section */ 319 | 320 | /* Begin XCBuildConfiguration section */ 321 | 05313D161FD9A99E006FB69A /* Debug */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | CODE_SIGN_STYLE = Automatic; 325 | MACOSX_DEPLOYMENT_TARGET = 10.7; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | }; 328 | name = Debug; 329 | }; 330 | 05313D171FD9A99E006FB69A /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | CODE_SIGN_STYLE = Automatic; 334 | MACOSX_DEPLOYMENT_TARGET = 10.7; 335 | PRODUCT_NAME = "$(TARGET_NAME)"; 336 | }; 337 | name = Release; 338 | }; 339 | 059BEC781FE30C0F00E4879A /* Debug */ = { 340 | isa = XCBuildConfiguration; 341 | buildSettings = { 342 | CODE_SIGN_STYLE = Automatic; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | }; 345 | name = Debug; 346 | }; 347 | 059BEC791FE30C0F00E4879A /* Release */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | CODE_SIGN_STYLE = Automatic; 351 | PRODUCT_NAME = "$(TARGET_NAME)"; 352 | }; 353 | name = Release; 354 | }; 355 | 05C21B3F1FD9A59000DDAC9B /* Debug */ = { 356 | isa = XCBuildConfiguration; 357 | buildSettings = { 358 | ALWAYS_SEARCH_USER_PATHS = NO; 359 | CLANG_ANALYZER_NONNULL = YES; 360 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 361 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 362 | CLANG_CXX_LIBRARY = "libc++"; 363 | CLANG_ENABLE_MODULES = YES; 364 | CLANG_ENABLE_OBJC_ARC = YES; 365 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 366 | CLANG_WARN_BOOL_CONVERSION = YES; 367 | CLANG_WARN_COMMA = YES; 368 | CLANG_WARN_CONSTANT_CONVERSION = YES; 369 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 370 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 371 | CLANG_WARN_EMPTY_BODY = YES; 372 | CLANG_WARN_ENUM_CONVERSION = YES; 373 | CLANG_WARN_INFINITE_RECURSION = YES; 374 | CLANG_WARN_INT_CONVERSION = YES; 375 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 376 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 377 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 378 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 379 | CLANG_WARN_STRICT_PROTOTYPES = YES; 380 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 381 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 382 | CLANG_WARN_UNREACHABLE_CODE = YES; 383 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 384 | CODE_SIGN_IDENTITY = "-"; 385 | COPY_PHASE_STRIP = NO; 386 | DEBUG_INFORMATION_FORMAT = dwarf; 387 | ENABLE_STRICT_OBJC_MSGSEND = YES; 388 | ENABLE_TESTABILITY = YES; 389 | GCC_C_LANGUAGE_STANDARD = gnu11; 390 | GCC_DYNAMIC_NO_PIC = NO; 391 | GCC_NO_COMMON_BLOCKS = YES; 392 | GCC_OPTIMIZATION_LEVEL = 0; 393 | GCC_PREPROCESSOR_DEFINITIONS = ( 394 | "DEBUG=1", 395 | "$(inherited)", 396 | ); 397 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 398 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 399 | GCC_WARN_UNDECLARED_SELECTOR = YES; 400 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 401 | GCC_WARN_UNUSED_FUNCTION = YES; 402 | GCC_WARN_UNUSED_VARIABLE = YES; 403 | MACOSX_DEPLOYMENT_TARGET = 10.12; 404 | MTL_ENABLE_DEBUG_INFO = YES; 405 | ONLY_ACTIVE_ARCH = YES; 406 | SDKROOT = macosx; 407 | }; 408 | name = Debug; 409 | }; 410 | 05C21B401FD9A59000DDAC9B /* Release */ = { 411 | isa = XCBuildConfiguration; 412 | buildSettings = { 413 | ALWAYS_SEARCH_USER_PATHS = NO; 414 | CLANG_ANALYZER_NONNULL = YES; 415 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 416 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 417 | CLANG_CXX_LIBRARY = "libc++"; 418 | CLANG_ENABLE_MODULES = YES; 419 | CLANG_ENABLE_OBJC_ARC = YES; 420 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 421 | CLANG_WARN_BOOL_CONVERSION = YES; 422 | CLANG_WARN_COMMA = YES; 423 | CLANG_WARN_CONSTANT_CONVERSION = YES; 424 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 425 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 426 | CLANG_WARN_EMPTY_BODY = YES; 427 | CLANG_WARN_ENUM_CONVERSION = YES; 428 | CLANG_WARN_INFINITE_RECURSION = YES; 429 | CLANG_WARN_INT_CONVERSION = YES; 430 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 431 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 432 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 433 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 434 | CLANG_WARN_STRICT_PROTOTYPES = YES; 435 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 436 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 437 | CLANG_WARN_UNREACHABLE_CODE = YES; 438 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 439 | CODE_SIGN_IDENTITY = "-"; 440 | COPY_PHASE_STRIP = NO; 441 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 442 | ENABLE_NS_ASSERTIONS = NO; 443 | ENABLE_STRICT_OBJC_MSGSEND = YES; 444 | GCC_C_LANGUAGE_STANDARD = gnu11; 445 | GCC_NO_COMMON_BLOCKS = YES; 446 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 447 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 448 | GCC_WARN_UNDECLARED_SELECTOR = YES; 449 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 450 | GCC_WARN_UNUSED_FUNCTION = YES; 451 | GCC_WARN_UNUSED_VARIABLE = YES; 452 | MACOSX_DEPLOYMENT_TARGET = 10.12; 453 | MTL_ENABLE_DEBUG_INFO = NO; 454 | SDKROOT = macosx; 455 | }; 456 | name = Release; 457 | }; 458 | 05C21B421FD9A59000DDAC9B /* Debug */ = { 459 | isa = XCBuildConfiguration; 460 | buildSettings = { 461 | CODE_SIGN_STYLE = Automatic; 462 | EXECUTABLE_PREFIX = ""; 463 | GCC_ENABLE_CPP_EXCEPTIONS = YES; 464 | GCC_ENABLE_CPP_RTTI = YES; 465 | MACOSX_DEPLOYMENT_TARGET = 10.7; 466 | PRODUCT_NAME = "$(TARGET_NAME)"; 467 | }; 468 | name = Debug; 469 | }; 470 | 05C21B431FD9A59000DDAC9B /* Release */ = { 471 | isa = XCBuildConfiguration; 472 | buildSettings = { 473 | CODE_SIGN_STYLE = Automatic; 474 | EXECUTABLE_PREFIX = ""; 475 | GCC_ENABLE_CPP_EXCEPTIONS = YES; 476 | GCC_ENABLE_CPP_RTTI = YES; 477 | MACOSX_DEPLOYMENT_TARGET = 10.7; 478 | PRODUCT_NAME = "$(TARGET_NAME)"; 479 | }; 480 | name = Release; 481 | }; 482 | /* End XCBuildConfiguration section */ 483 | 484 | /* Begin XCConfigurationList section */ 485 | 05313D151FD9A99E006FB69A /* Build configuration list for PBXNativeTarget "demo" */ = { 486 | isa = XCConfigurationList; 487 | buildConfigurations = ( 488 | 05313D161FD9A99E006FB69A /* Debug */, 489 | 05313D171FD9A99E006FB69A /* Release */, 490 | ); 491 | defaultConfigurationIsVisible = 0; 492 | defaultConfigurationName = Release; 493 | }; 494 | 059BEC7A1FE30C0F00E4879A /* Build configuration list for PBXNativeTarget "replay" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | 059BEC781FE30C0F00E4879A /* Debug */, 498 | 059BEC791FE30C0F00E4879A /* Release */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Release; 502 | }; 503 | 05C21B311FD9A59000DDAC9B /* Build configuration list for PBXProject "libntstat" */ = { 504 | isa = XCConfigurationList; 505 | buildConfigurations = ( 506 | 05C21B3F1FD9A59000DDAC9B /* Debug */, 507 | 05C21B401FD9A59000DDAC9B /* Release */, 508 | ); 509 | defaultConfigurationIsVisible = 0; 510 | defaultConfigurationName = Release; 511 | }; 512 | 05C21B411FD9A59000DDAC9B /* Build configuration list for PBXNativeTarget "libntstat" */ = { 513 | isa = XCConfigurationList; 514 | buildConfigurations = ( 515 | 05C21B421FD9A59000DDAC9B /* Debug */, 516 | 05C21B431FD9A59000DDAC9B /* Release */, 517 | ); 518 | defaultConfigurationIsVisible = 0; 519 | defaultConfigurationName = Release; 520 | }; 521 | /* End XCConfigurationList section */ 522 | }; 523 | rootObject = 05C21B2E1FD9A59000DDAC9B /* Project object */; 524 | } 525 | -------------------------------------------------------------------------------- /replay/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // libntstat demo 3 | // 4 | // Copyright © 2017 Alex Malone. All rights reserved. 5 | 6 | #include "../include/NetworkStatisticsClient.hpp" 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | string stream2text (const NTStatStreamKey& s); 13 | string timestr(); 14 | std::string stateToText(const NTStatStream *stream); 15 | 16 | /* 17 | * Implementing this listener allows receipt of events. 18 | */ 19 | class MyNetstatListener : public NetworkStatisticsListener 20 | { 21 | virtual void onStreamAdded(const NTStatStream *stream) 22 | { 23 | log(stream, '+'); 24 | } 25 | virtual void onStreamRemoved(const NTStatStream *stream) 26 | { 27 | log(stream, '-'); 28 | } 29 | virtual void onStreamStatsUpdate(const NTStatStream *stream) 30 | { 31 | log(stream, '#'); 32 | } 33 | 34 | 35 | void log(const NTStatStream* stream, char displayChar) 36 | { 37 | if (IS_LISTEN_PORT(stream)) 38 | { 39 | printf(" @%c %s pid:%u (%s) LISTEN %s port:%u\n", displayChar, timestr().c_str(), stream->process.pid, 40 | stream->process.name,(stream->key.ipproto == IPPROTO_TCP ? "TCP" : "UDP"), ntohs(stream->key.lport)); 41 | } 42 | else 43 | { 44 | //string stateStr = (displayChar == '-' ? stateToText(stream) : ""); 45 | string notes = ""; 46 | if (displayChar == '-' && stream->key.ipproto == IPPROTO_TCP && 47 | stream->stats.rxpackets == 0) notes = "FAILED"; 48 | 49 | printf(" %c %s %s pid:%u (%s) %s id:%llu\n", displayChar, timestr().c_str(), 50 | stream2text(stream->key).c_str(), stream->process.pid, stream->process.name, notes.c_str(), stream->id); 51 | 52 | // write bytes if present on update/remove 53 | 54 | string medium = "wired"; 55 | if (stream->stats.cell_txbytes > 0) medium = "cell"; 56 | if (stream->stats.wifi_txbytes > 0) medium = "wifi"; 57 | 58 | if (displayChar != '+' && (stream->stats.rxpackets > 0 || stream->stats.txpackets > 0)) 59 | printf(" bytes (tx/rx):%llu/%llu packets:%llu/%llu %s\n",stream->stats.txbytes, stream->stats.rxbytes, stream->stats.txpackets, stream->stats.rxpackets, medium.c_str()); 60 | } 61 | } 62 | 63 | }; 64 | 65 | int main(int argc, const char * argv[]) 66 | { 67 | const char *filename; 68 | unsigned int xnuVersion=0; 69 | 70 | // get filename, xnuVersion from args 71 | 72 | if (argc != 3) { printf("usage: replay \n"); exit(2); } 73 | xnuVersion = atoi(argv[1]); 74 | filename = argv[2]; 75 | 76 | if (xnuVersion < 2000 || xnuVersion > 5000) { printf("xnuVersion\n"); exit(3); } 77 | 78 | // create 79 | 80 | MyNetstatListener listener = MyNetstatListener(); 81 | NetworkStatisticsClient* netstatClient = NetworkStatisticsClientNew(&listener); 82 | 83 | // replay messages from file 84 | 85 | netstatClient->runRecording((char *)filename, xnuVersion); 86 | 87 | return 0; 88 | } 89 | 90 | // ==================== helper functions ====================== 91 | 92 | #include 93 | 94 | string addr2text ( const in_addr& Addr ) 95 | { 96 | char IPv4AddressAsString[INET_ADDRSTRLEN]; //buffer needs 16 characters min 97 | if ( NULL != inet_ntop ( AF_INET, &Addr, IPv4AddressAsString, sizeof(IPv4AddressAsString) ) ) 98 | return string(IPv4AddressAsString); 99 | return "?"; 100 | } 101 | 102 | string addr2text ( const in6_addr& Addr ) 103 | { 104 | char IPv6AddressAsString[INET6_ADDRSTRLEN]; //buffer needs 46 characters min 105 | if ( NULL != inet_ntop ( AF_INET6, &Addr, IPv6AddressAsString, sizeof(IPv6AddressAsString) ) ) 106 | return string(IPv6AddressAsString); 107 | return "?"; 108 | } 109 | 110 | string stream2text (const NTStatStreamKey& s) 111 | { 112 | char tmp[256]; 113 | string val = s.ipproto == IPPROTO_TCP ? "TCP " : "UDP "; 114 | if (s.isV6) 115 | { 116 | val += addr2text(s.local.addr6); 117 | sprintf(tmp," %d - ", ntohs(s.lport)); 118 | val += tmp; 119 | val += addr2text(s.remote.addr6); 120 | sprintf(tmp," %d", ntohs(s.rport)); 121 | val += tmp; 122 | } else { 123 | val += addr2text(s.local.addr4); 124 | sprintf(tmp," %d - ", ntohs(s.lport)); 125 | val += tmp; 126 | val += addr2text(s.remote.addr4); 127 | sprintf(tmp," %d", ntohs(s.rport)); 128 | val += tmp; 129 | } 130 | return val; 131 | } 132 | 133 | std::string stateToText(const NTStatStream *stream) 134 | { 135 | switch(stream->states.state) 136 | { 137 | case TCPS_CLOSED: return ("CLOSED"); 138 | case TCPS_LISTEN: return ("LISTENING"); 139 | case TCPS_ESTABLISHED: return ("ESTABLISHED"); 140 | case TCPS_CLOSING: return ("CLOSING"); 141 | case TCPS_SYN_SENT: return ("SYN_SENT"); 142 | case TCPS_LAST_ACK: return ("LAST_ACK"); 143 | case TCPS_CLOSE_WAIT: return ("CLOSE_WAIT"); 144 | case TCPS_TIME_WAIT: return ("TIME_WAIT"); 145 | case TCPS_FIN_WAIT_1 : return ("FIN_WAIT_1"); 146 | case TCPS_FIN_WAIT_2 : return ("FIN_WAIT_2"); 147 | 148 | default: 149 | return("?"); 150 | } 151 | 152 | } // stateToText 153 | 154 | #include 155 | string timestr() 156 | { 157 | char timestamp[64]=""; 158 | time_t now = time(NULL); 159 | struct tm *tm = localtime(&now); 160 | strftime(timestamp, 63, "%H:%M:%S", tm); 161 | return string(timestamp); 162 | } 163 | 164 | -------------------------------------------------------------------------------- /src/NTStatKernelStructHandler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _NT_STAT_KERNEL_STRUCT_HANDLER_H_ 2 | #define _NT_STAT_KERNEL_STRUCT_HANDLER_H_ 3 | 4 | #include 5 | #include "../include/NetworkStatisticsClient.hpp" 6 | 7 | // the message header is consistent across versions, so defining here 8 | 9 | typedef struct nstat_msg_hdr 10 | { 11 | uint64_t context __attribute__((aligned(sizeof(u_int64_t)))); 12 | uint32_t type; 13 | uint16_t length; 14 | uint16_t flags; 15 | } nstat_msg_hdr; 16 | 17 | class MsgDest 18 | { 19 | public: 20 | /* 21 | * Returns current message sequence number. 22 | * StructHandlers need to use this value in the hdr.context of each message. 23 | */ 24 | virtual uint64_t seqnum() = 0; 25 | 26 | /* 27 | * send message 28 | */ 29 | virtual void send(nstat_msg_hdr* msg, size_t msglen) = 0; 30 | }; 31 | 32 | 33 | /* 34 | * Abstraction for reading and writing versioned kernel structs. 35 | * In XNU-3789 (NSTAT_REVISION 8), srcRef became uint64_t. Prior versions 36 | * need to convert to uint32_t. 37 | */ 38 | class NTStatKernelStructHandler 39 | { 40 | public: 41 | 42 | /* 43 | * write NSTAT_MSG_TYPE_GET_SRC_DESC to dest 44 | */ 45 | virtual void writeSrcDesc(MsgDest &dest, uint64_t providerId, uint64_t srcRef ) = 0; 46 | 47 | /* 48 | * write NSTAT_MSG_TYPE_ADD_ALL_SRCS for TCP or UDP 49 | */ 50 | virtual void writeAddAllTcpSrc(MsgDest &dest) = 0; 51 | virtual void writeAddAllUdpSrc(MsgDest &dest) = 0; 52 | 53 | /* 54 | * Provider IDs are abstracted. Some versions have multiple TCP and UDP. 55 | * In v3789, UDP changes from 3 to 4. Early versions don't have interface provider. 56 | * Thus, we resort to querying. 57 | */ 58 | virtual bool isProviderTcp(uint64_t providerId)=0; 59 | virtual bool isProviderUdp(uint64_t providerId)=0; 60 | 61 | /* 62 | * write NSTAT_MSG_TYPE_QUERY_SRC 63 | */ 64 | virtual void writeQuerySrc(MsgDest &dest, uint64_t srcRef) = 0; 65 | 66 | 67 | /* 68 | * Extract from msg and populate srcRef and providerId (if in message). 69 | */ 70 | virtual void getSrcRef(nstat_msg_hdr* msg, int structlen, uint64_t &srcRef, uint32_t &providerId) = 0; 71 | 72 | /* 73 | * Read src desc and populate relevant fields in dest. 74 | */ 75 | virtual bool readSrcDesc(nstat_msg_hdr*msg, int structlen, NTStatStream* dest ) = 0; 76 | 77 | /* 78 | * Update dest counts using msg. 79 | */ 80 | virtual void readCounts(nstat_msg_hdr*msg, int structlen, NTStatCounters& dest ) = 0; 81 | 82 | }; 83 | 84 | // macro for consistency in setting hdr fields. context in particular 85 | 86 | #define NTSTAT_MSG_HDR(msg_struct, MsgDestRef, MSG_TYPE) { \ 87 | (msg_struct).hdr.type = MSG_TYPE; \ 88 | (msg_struct).hdr.length = sizeof(msg_struct); \ 89 | (msg_struct).hdr.context = (MsgDestRef).seqnum(); \ 90 | } 91 | 92 | #endif // _NT_STAT_KERNEL_STRUCT_HANDLER_H_ 93 | -------------------------------------------------------------------------------- /src/ntstat_kernel_2050.h: -------------------------------------------------------------------------------- 1 | // definitions from bsd/net/ntstat.h kernel header 2 | // https://github.com/apple/darwin-xnu 3 | // git checkout xnu-2050.48.11 4 | // Lion 10.7 5 | 6 | #pragma pack(push, 4) 7 | #pragma mark -- Common Data Structures -- 8 | 9 | #define __NSTAT_REVISION__ 1 10 | 11 | typedef u_int32_t nstat_provider_id_t; 12 | typedef u_int32_t nstat_src_ref_t; 13 | 14 | typedef struct nstat_counts 15 | { 16 | /* Counters */ 17 | u_int64_t nstat_rxpackets __attribute__((aligned(8))); 18 | u_int64_t nstat_rxbytes __attribute__((aligned(8))); 19 | u_int64_t nstat_txpackets __attribute__((aligned(8))); 20 | u_int64_t nstat_txbytes __attribute__((aligned(8))); 21 | 22 | u_int32_t nstat_rxduplicatebytes; 23 | u_int32_t nstat_rxoutoforderbytes; 24 | u_int32_t nstat_txretransmit; 25 | 26 | u_int32_t nstat_connectattempts; 27 | u_int32_t nstat_connectsuccesses; 28 | 29 | u_int32_t nstat_min_rtt; 30 | u_int32_t nstat_avg_rtt; 31 | u_int32_t nstat_var_rtt; 32 | } nstat_counts; 33 | 34 | #pragma mark -- Network Statistics Providers -- 35 | 36 | enum 37 | { 38 | NSTAT_PROVIDER_ROUTE = 1 39 | ,NSTAT_PROVIDER_TCP = 2 40 | ,NSTAT_PROVIDER_UDP = 3 41 | }; 42 | 43 | typedef struct nstat_route_add_param 44 | { 45 | union 46 | { 47 | struct sockaddr_in v4; 48 | struct sockaddr_in6 v6; 49 | } dst; 50 | union 51 | { 52 | struct sockaddr_in v4; 53 | struct sockaddr_in6 v6; 54 | } mask; 55 | u_int32_t ifindex; 56 | } nstat_route_add_param; 57 | 58 | typedef struct nstat_tcp_add_param 59 | { 60 | union 61 | { 62 | struct sockaddr_in v4; 63 | struct sockaddr_in6 v6; 64 | } local; 65 | union 66 | { 67 | struct sockaddr_in v4; 68 | struct sockaddr_in6 v6; 69 | } remote; 70 | } nstat_tcp_add_param; 71 | 72 | typedef struct nstat_tcp_descriptor 73 | { 74 | union 75 | { 76 | struct sockaddr_in v4; 77 | struct sockaddr_in6 v6; 78 | } local; 79 | 80 | union 81 | { 82 | struct sockaddr_in v4; 83 | struct sockaddr_in6 v6; 84 | } remote; 85 | 86 | u_int32_t ifindex; 87 | 88 | u_int32_t state; 89 | 90 | u_int32_t sndbufsize; 91 | u_int32_t sndbufused; 92 | u_int32_t rcvbufsize; 93 | u_int32_t rcvbufused; 94 | u_int32_t txunacked; 95 | u_int32_t txwindow; 96 | u_int32_t txcwindow; 97 | u_int32_t traffic_class; 98 | 99 | u_int64_t upid; 100 | u_int32_t pid; 101 | char pname[64]; 102 | } nstat_tcp_descriptor; 103 | 104 | typedef struct nstat_tcp_add_param nstat_udp_add_param; 105 | 106 | typedef struct nstat_udp_descriptor 107 | { 108 | union 109 | { 110 | struct sockaddr_in v4; 111 | struct sockaddr_in6 v6; 112 | } local; 113 | 114 | union 115 | { 116 | struct sockaddr_in v4; 117 | struct sockaddr_in6 v6; 118 | } remote; 119 | 120 | u_int32_t ifindex; 121 | 122 | u_int32_t rcvbufsize; 123 | u_int32_t rcvbufused; 124 | u_int32_t traffic_class; 125 | 126 | u_int64_t upid; 127 | u_int32_t pid; 128 | char pname[64]; 129 | } nstat_udp_descriptor; 130 | 131 | typedef struct nstat_route_descriptor 132 | { 133 | u_int64_t id; 134 | u_int64_t parent_id; 135 | u_int64_t gateway_id; 136 | 137 | union 138 | { 139 | struct sockaddr_in v4; 140 | struct sockaddr_in6 v6; 141 | struct sockaddr sa; 142 | } dst; 143 | 144 | union 145 | { 146 | struct sockaddr_in v4; 147 | struct sockaddr_in6 v6; 148 | struct sockaddr sa; 149 | } mask; 150 | 151 | union 152 | { 153 | struct sockaddr_in v4; 154 | struct sockaddr_in6 v6; 155 | struct sockaddr sa; 156 | } gateway; 157 | 158 | u_int32_t ifindex; 159 | u_int32_t flags; 160 | 161 | } nstat_route_descriptor; 162 | 163 | #pragma mark -- Network Statistics User Client -- 164 | 165 | #define NET_STAT_CONTROL_NAME "com.apple.network.statistics" 166 | 167 | enum 168 | { 169 | // generic response messages 170 | NSTAT_MSG_TYPE_SUCCESS = 0 171 | ,NSTAT_MSG_TYPE_ERROR = 1 172 | 173 | // Requests 174 | ,NSTAT_MSG_TYPE_ADD_SRC = 1001 175 | ,NSTAT_MSG_TYPE_ADD_ALL_SRCS = 1002 176 | ,NSTAT_MSG_TYPE_REM_SRC = 1003 177 | ,NSTAT_MSG_TYPE_QUERY_SRC = 1004 178 | ,NSTAT_MSG_TYPE_GET_SRC_DESC = 1005 179 | 180 | // Responses/Notfications 181 | ,NSTAT_MSG_TYPE_SRC_ADDED = 10001 182 | ,NSTAT_MSG_TYPE_SRC_REMOVED = 10002 183 | ,NSTAT_MSG_TYPE_SRC_DESC = 10003 184 | ,NSTAT_MSG_TYPE_SRC_COUNTS = 10004 185 | }; 186 | 187 | enum 188 | { 189 | NSTAT_SRC_REF_ALL = 0xffffffff 190 | ,NSTAT_SRC_REF_INVALID = 0 191 | }; 192 | 193 | typedef struct nstat_msg_hdr 194 | { 195 | u_int64_t context; 196 | u_int32_t type; 197 | u_int32_t pad; // unused for now 198 | } nstat_msg_hdr; 199 | 200 | typedef struct nstat_msg_error 201 | { 202 | nstat_msg_hdr hdr; 203 | u_int32_t error; // errno error 204 | } nstat_msg_error; 205 | 206 | typedef struct nstat_msg_add_src 207 | { 208 | nstat_msg_hdr hdr; 209 | nstat_provider_id_t provider; 210 | u_int8_t param[]; 211 | } nstat_msg_add_src_req; 212 | 213 | typedef struct nstat_msg_add_all_srcs 214 | { 215 | nstat_msg_hdr hdr; 216 | nstat_provider_id_t provider; 217 | } nstat_msg_add_all_srcs; 218 | 219 | typedef struct nstat_msg_src_added 220 | { 221 | nstat_msg_hdr hdr; 222 | nstat_provider_id_t provider; 223 | nstat_src_ref_t srcref; 224 | } nstat_msg_src_added; 225 | 226 | typedef struct nstat_msg_rem_src 227 | { 228 | nstat_msg_hdr hdr; 229 | nstat_src_ref_t srcref; 230 | } nstat_msg_rem_src_req; 231 | 232 | typedef struct nstat_msg_get_src_description 233 | { 234 | nstat_msg_hdr hdr; 235 | nstat_src_ref_t srcref; 236 | } nstat_msg_get_src_description; 237 | 238 | typedef struct nstat_msg_src_description 239 | { 240 | nstat_msg_hdr hdr; 241 | nstat_src_ref_t srcref; 242 | nstat_provider_id_t provider; 243 | u_int8_t data[]; 244 | } nstat_msg_src_description; 245 | 246 | typedef struct nstat_msg_query_src 247 | { 248 | nstat_msg_hdr hdr; 249 | nstat_src_ref_t srcref; 250 | } nstat_msg_query_src_req; 251 | 252 | typedef struct nstat_msg_src_counts 253 | { 254 | nstat_msg_hdr hdr; 255 | nstat_src_ref_t srcref; 256 | nstat_counts counts; 257 | } nstat_msg_src_counts; 258 | 259 | typedef struct nstat_msg_src_removed 260 | { 261 | nstat_msg_hdr hdr; 262 | nstat_src_ref_t srcref; 263 | } nstat_msg_src_removed; 264 | 265 | #pragma pack(pop) 266 | -------------------------------------------------------------------------------- /src/ntstat_kernel_2422.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "NTStatKernelStructHandler.hpp" 3 | 4 | // definitions from darwin-xnu/bsd/net/ntstat.h kernel header 5 | 6 | #include 7 | 8 | #include "ntstat_kernel_2422.h" 9 | 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | class NTStatKernel2422 : public NTStatKernelStructHandler 15 | { 16 | public: 17 | virtual bool isProviderTcp(uint64_t providerId){ 18 | return (NSTAT_PROVIDER_TCP == providerId);} 19 | 20 | virtual bool isProviderUdp(uint64_t providerId) { 21 | return (NSTAT_PROVIDER_UDP == providerId);} 22 | 23 | virtual bool isProviderInterface(uint64_t providerId) { return NSTAT_PROVIDER_IFNET == providerId; } 24 | 25 | //-------------------------------------------------------------------- 26 | // write GET_SRC_DESC message to dest 27 | //-------------------------------------------------------------------- 28 | virtual void writeSrcDesc(MsgDest &dest, uint64_t providerId, uint64_t srcRef ) 29 | { 30 | nstat_msg_get_src_description msg = nstat_msg_get_src_description(); 31 | 32 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_GET_SRC_DESC); 33 | 34 | msg.srcref = (nstat_src_ref_t)srcRef; 35 | 36 | dest.send(&msg.hdr, sizeof(msg)); 37 | } 38 | 39 | //-------------------------------------------------------------------- 40 | // write QUERY_SRC message to dest 41 | //-------------------------------------------------------------------- 42 | virtual void writeQuerySrc(MsgDest &dest, uint64_t srcRef) 43 | { 44 | nstat_msg_query_src_req msg = nstat_msg_query_src_req(); 45 | 46 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_QUERY_SRC); 47 | 48 | msg.srcref= (nstat_src_ref_t)srcRef; 49 | 50 | dest.send(&msg.hdr, sizeof(msg)); 51 | } 52 | 53 | //-------------------------------------------------------------------- 54 | // write ADD_ADD_SRCS message to dest 55 | //-------------------------------------------------------------------- 56 | virtual void writeAddAllSrc(MsgDest &dest, uint32_t providerId) 57 | { 58 | nstat_msg_add_all_srcs msg = nstat_msg_add_all_srcs(); 59 | 60 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_ADD_ALL_SRCS); 61 | 62 | msg.provider = providerId ; 63 | 64 | dest.send(&msg.hdr, sizeof(msg)); 65 | } 66 | 67 | // xnu-3789 is first time we see split _KERNEL and _USERLAND 68 | 69 | virtual void writeAddAllTcpSrc(MsgDest &dest) { 70 | writeAddAllSrc(dest, NSTAT_PROVIDER_TCP); 71 | } 72 | 73 | virtual void writeAddAllUdpSrc(MsgDest &dest) { 74 | writeAddAllSrc(dest, NSTAT_PROVIDER_UDP); 75 | } 76 | 77 | virtual void writeAddAllInterfaces(MsgDest &dest) { 78 | writeAddAllSrc(dest, NSTAT_PROVIDER_IFNET); 79 | } 80 | 81 | //-------------------------------------------------------------------- 82 | // extract srcRef, providerId (if possible) from message 83 | //-------------------------------------------------------------------- 84 | virtual void getSrcRef(nstat_msg_hdr* msg, int structlen, uint64_t &srcRef, uint32_t &providerId) { 85 | switch(msg->type) 86 | { 87 | case NSTAT_MSG_TYPE_SRC_COUNTS: 88 | srcRef = ((nstat_msg_src_counts*)msg)->srcref; 89 | break; 90 | case NSTAT_MSG_TYPE_SRC_DESC: 91 | srcRef = ((nstat_msg_src_description*)msg)->srcref; 92 | providerId = ((nstat_msg_src_description*)msg)->provider; 93 | break; 94 | case NSTAT_MSG_TYPE_SRC_ADDED: 95 | srcRef = ((nstat_msg_src_added*)msg)->srcref; 96 | providerId = ((nstat_msg_src_added*)msg)->provider; 97 | break; 98 | case NSTAT_MSG_TYPE_SRC_REMOVED: 99 | srcRef = ((nstat_msg_src_removed*)msg)->srcref; 100 | break; 101 | case NSTAT_MSG_TYPE_QUERY_SRC: 102 | srcRef = ((nstat_msg_query_src*)msg)->srcref; 103 | break; 104 | case NSTAT_MSG_TYPE_GET_SRC_DESC: 105 | srcRef = ((nstat_msg_get_src_description*)msg)->srcref; 106 | break; 107 | case NSTAT_MSG_TYPE_REM_SRC: 108 | srcRef = ((nstat_msg_rem_src*)msg)->srcref; 109 | break; 110 | //case NSTAT_MSG_TYPE_ADD_SRC: 111 | //case NSTAT_MSG_TYPE_ADD_ALL_SRCS: 112 | default: 113 | //printf("E getSrcRef not implemented for type %d\n", msg->type); 114 | break; 115 | } 116 | } 117 | 118 | //-------------------------------------------------------------------- 119 | // populate dest with message data 120 | //-------------------------------------------------------------------- 121 | virtual bool readSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 122 | { 123 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 124 | if (msg->provider == NSTAT_PROVIDER_TCP) { 125 | readTcpSrcDesc(hdr, structlen, dest); 126 | } else if (msg->provider == NSTAT_PROVIDER_UDP) { 127 | readUdpSrcDesc(hdr, structlen, dest); 128 | } else { 129 | // ?? 130 | return false; 131 | } 132 | return true; 133 | } 134 | 135 | //-------------------------------------------------------------------- 136 | // populate dest with message ifnet data 137 | //-------------------------------------------------------------------- 138 | /* 139 | virtual bool readSrcDesc(nstat_msg_hdr* hdr, int structlen, NTStatInterface* dest ) 140 | { 141 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 142 | if (msg->provider != NSTAT_PROVIDER_IFNET) return false; 143 | 144 | nstat_ifnet_descriptor* ifnet = (nstat_ifnet_descriptor*)msg->data; 145 | dest->name = string(ifnet->name); 146 | dest->description = string(ifnet->description); 147 | dest->ifindex = ifnet->ifindex; 148 | dest->type = ifnet->type; 149 | 150 | return false; 151 | }*/ 152 | 153 | //-------------------------------------------------------------------- 154 | // TCP: populate dest with message data 155 | //-------------------------------------------------------------------- 156 | virtual void readTcpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 157 | { 158 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 159 | nstat_tcp_descriptor*tcp = (nstat_tcp_descriptor*)msg->data; 160 | 161 | dest->key.ifindex = tcp->ifindex; 162 | dest->key.ipproto = IPPROTO_TCP; 163 | dest->key.isV6 = (tcp->local.v4.sin_family == AF_INET6); 164 | 165 | if (tcp->local.v4.sin_family == AF_INET6) 166 | { 167 | dest->key.lport = tcp->local.v6.sin6_port; 168 | dest->key.local.addr6 = tcp->local.v6.sin6_addr; 169 | dest->key.rport = tcp->remote.v6.sin6_port; 170 | dest->key.remote.addr6 = tcp->remote.v6.sin6_addr; 171 | } else { 172 | dest->key.lport = tcp->local.v4.sin_port; 173 | dest->key.rport = tcp->remote.v4.sin_port; 174 | dest->key.local.addr4 = tcp->local.v4.sin_addr; 175 | dest->key.remote.addr4 = tcp->remote.v4.sin_addr; 176 | } 177 | dest->states.txwindow = tcp->txwindow; 178 | dest->states.txcwindow = tcp->txcwindow; 179 | dest->states.state = tcp->state; 180 | 181 | dest->process.pid = tcp->pid; 182 | 183 | strcpy(dest->process.name, ((tcp->pid > 0 && tcp->pname[0]) ? tcp->pname : "")); 184 | } 185 | 186 | //-------------------------------------------------------------------- 187 | // UDP: populate dest with message data 188 | //-------------------------------------------------------------------- 189 | virtual void readUdpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 190 | { 191 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 192 | nstat_udp_descriptor*udp = (nstat_udp_descriptor*)msg->data; 193 | 194 | dest->key.ifindex = udp->ifindex; 195 | dest->key.ipproto = IPPROTO_UDP; 196 | dest->key.isV6 = (udp->local.v4.sin_family == AF_INET6); 197 | 198 | if (udp->local.v4.sin_family == AF_INET6) 199 | { 200 | dest->key.lport = udp->local.v6.sin6_port; 201 | dest->key.local.addr6 = udp->local.v6.sin6_addr; 202 | dest->key.rport = udp->remote.v6.sin6_port; 203 | dest->key.remote.addr6 = udp->remote.v6.sin6_addr; 204 | } else { 205 | dest->key.lport = udp->local.v4.sin_port; 206 | dest->key.rport = udp->remote.v4.sin_port; 207 | dest->key.local.addr4 = udp->local.v4.sin_addr; 208 | dest->key.remote.addr4 = udp->remote.v4.sin_addr; 209 | } 210 | 211 | dest->process.pid = udp->pid; 212 | 213 | strcpy(dest->process.name, ((udp->pid > 0 && udp->pname[0]) ? udp->pname : "")); 214 | } 215 | 216 | //-------------------------------------------------------------------- 217 | // populate dest with message counts data 218 | //-------------------------------------------------------------------- 219 | virtual void readCounts(nstat_msg_hdr*hdr, int structlen, NTStatCounters& dest ) 220 | { 221 | nstat_msg_src_counts *msg = (nstat_msg_src_counts*)hdr; 222 | dest.rxbytes = msg->counts.nstat_rxbytes; 223 | dest.txbytes = msg->counts.nstat_txbytes; 224 | dest.rxpackets = msg->counts.nstat_rxpackets; 225 | dest.txpackets = msg->counts.nstat_txpackets; 226 | 227 | dest.cell_rxbytes = msg->counts.nstat_cell_rxbytes; 228 | dest.cell_txbytes = msg->counts.nstat_cell_txbytes; 229 | 230 | dest.wifi_rxbytes = msg->counts.nstat_wifi_rxbytes; 231 | dest.wifi_txbytes = msg->counts.nstat_wifi_txbytes; 232 | } 233 | 234 | }; 235 | 236 | 237 | NTStatKernelStructHandler* NewNTStatKernel2422() { 238 | return new NTStatKernel2422(); 239 | } 240 | -------------------------------------------------------------------------------- /src/ntstat_kernel_2422.h: -------------------------------------------------------------------------------- 1 | // https://github.com/apple/darwin-xnu 2 | // git checkout xnu-2422.115.4 3 | // Mavericks 10.9 4 | 5 | // bsd/netinet/tcp.h 6 | struct tcp_conn_status { 7 | unsigned int probe_activated : 1; 8 | unsigned int write_probe_failed : 1; 9 | unsigned int read_probe_failed : 1; 10 | unsigned int conn_probe_failed : 1; 11 | }; 12 | #define IFNAMSIZ 16 13 | 14 | // bsd/net/ntstat.h 15 | 16 | #pragma pack(push, 4) 17 | #pragma mark -- Common Data Structures -- 18 | 19 | #define __NSTAT_REVISION__ 4 20 | 21 | typedef u_int32_t nstat_provider_id_t; 22 | typedef u_int32_t nstat_src_ref_t; 23 | 24 | typedef struct nstat_counts 25 | { 26 | /* Counters */ 27 | u_int64_t nstat_rxpackets __attribute__((aligned(8))); 28 | u_int64_t nstat_rxbytes __attribute__((aligned(8))); 29 | u_int64_t nstat_txpackets __attribute__((aligned(8))); 30 | u_int64_t nstat_txbytes __attribute__((aligned(8))); 31 | 32 | u_int32_t nstat_rxduplicatebytes; 33 | u_int32_t nstat_rxoutoforderbytes; 34 | u_int32_t nstat_txretransmit; 35 | 36 | u_int32_t nstat_connectattempts; 37 | u_int32_t nstat_connectsuccesses; 38 | 39 | u_int32_t nstat_min_rtt; 40 | u_int32_t nstat_avg_rtt; 41 | u_int32_t nstat_var_rtt; 42 | 43 | u_int64_t nstat_cell_rxbytes __attribute__((aligned(8))); 44 | u_int64_t nstat_cell_txbytes __attribute__((aligned(8))); 45 | u_int64_t nstat_wifi_rxbytes __attribute__((aligned(8))); 46 | u_int64_t nstat_wifi_txbytes __attribute__((aligned(8))); 47 | } nstat_counts; 48 | 49 | #pragma mark -- Network Statistics Providers -- 50 | 51 | enum 52 | { 53 | NSTAT_PROVIDER_ROUTE = 1 54 | ,NSTAT_PROVIDER_TCP = 2 55 | ,NSTAT_PROVIDER_UDP = 3 56 | ,NSTAT_PROVIDER_IFNET = 4 57 | }; 58 | 59 | typedef struct nstat_route_add_param 60 | { 61 | union 62 | { 63 | struct sockaddr_in v4; 64 | struct sockaddr_in6 v6; 65 | } dst; 66 | union 67 | { 68 | struct sockaddr_in v4; 69 | struct sockaddr_in6 v6; 70 | } mask; 71 | u_int32_t ifindex; 72 | } nstat_route_add_param; 73 | 74 | typedef struct nstat_tcp_add_param 75 | { 76 | union 77 | { 78 | struct sockaddr_in v4; 79 | struct sockaddr_in6 v6; 80 | } local; 81 | union 82 | { 83 | struct sockaddr_in v4; 84 | struct sockaddr_in6 v6; 85 | } remote; 86 | } nstat_tcp_add_param; 87 | 88 | typedef struct nstat_tcp_descriptor 89 | { 90 | union 91 | { 92 | struct sockaddr_in v4; 93 | struct sockaddr_in6 v6; 94 | } local; 95 | 96 | union 97 | { 98 | struct sockaddr_in v4; 99 | struct sockaddr_in6 v6; 100 | } remote; 101 | 102 | u_int32_t ifindex; 103 | 104 | u_int32_t state; 105 | 106 | u_int32_t sndbufsize; 107 | u_int32_t sndbufused; 108 | u_int32_t rcvbufsize; 109 | u_int32_t rcvbufused; 110 | u_int32_t txunacked; 111 | u_int32_t txwindow; 112 | u_int32_t txcwindow; 113 | u_int32_t traffic_class; 114 | 115 | u_int64_t upid; 116 | u_int32_t pid; 117 | char pname[64]; 118 | u_int64_t eupid; 119 | u_int32_t epid; 120 | 121 | uint8_t uuid[16]; 122 | uint8_t euuid[16]; 123 | } nstat_tcp_descriptor; 124 | 125 | typedef struct nstat_tcp_add_param nstat_udp_add_param; 126 | 127 | typedef struct nstat_udp_descriptor 128 | { 129 | union 130 | { 131 | struct sockaddr_in v4; 132 | struct sockaddr_in6 v6; 133 | } local; 134 | 135 | union 136 | { 137 | struct sockaddr_in v4; 138 | struct sockaddr_in6 v6; 139 | } remote; 140 | 141 | u_int32_t ifindex; 142 | 143 | u_int32_t rcvbufsize; 144 | u_int32_t rcvbufused; 145 | u_int32_t traffic_class; 146 | 147 | u_int64_t upid; 148 | u_int32_t pid; 149 | char pname[64]; 150 | u_int64_t eupid; 151 | u_int32_t epid; 152 | 153 | uint8_t uuid[16]; 154 | uint8_t euuid[16]; 155 | } nstat_udp_descriptor; 156 | 157 | typedef struct nstat_route_descriptor 158 | { 159 | u_int64_t id; 160 | u_int64_t parent_id; 161 | u_int64_t gateway_id; 162 | 163 | union 164 | { 165 | struct sockaddr_in v4; 166 | struct sockaddr_in6 v6; 167 | struct sockaddr sa; 168 | } dst; 169 | 170 | union 171 | { 172 | struct sockaddr_in v4; 173 | struct sockaddr_in6 v6; 174 | struct sockaddr sa; 175 | } mask; 176 | 177 | union 178 | { 179 | struct sockaddr_in v4; 180 | struct sockaddr_in6 v6; 181 | struct sockaddr sa; 182 | } gateway; 183 | 184 | u_int32_t ifindex; 185 | u_int32_t flags; 186 | 187 | } nstat_route_descriptor; 188 | 189 | typedef struct nstat_ifnet_add_param 190 | { 191 | u_int32_t ifindex; 192 | u_int64_t threshold; 193 | } nstat_ifnet_add_param; 194 | 195 | #ifndef IF_DESCSIZE 196 | #define IF_DESCSIZE 128 197 | #endif 198 | typedef struct nstat_ifnet_descriptor 199 | { 200 | char name[IFNAMSIZ+1]; 201 | u_int32_t ifindex; 202 | u_int64_t threshold; 203 | unsigned int type; 204 | char description[IF_DESCSIZE]; 205 | } nstat_ifnet_descriptor; 206 | 207 | #pragma mark -- Network Statistics User Client -- 208 | 209 | #define NET_STAT_CONTROL_NAME "com.apple.network.statistics" 210 | 211 | 212 | enum 213 | { 214 | // generic response messages 215 | NSTAT_MSG_TYPE_SUCCESS = 0 216 | ,NSTAT_MSG_TYPE_ERROR = 1 217 | 218 | // Requests 219 | ,NSTAT_MSG_TYPE_ADD_SRC = 1001 220 | ,NSTAT_MSG_TYPE_ADD_ALL_SRCS = 1002 221 | ,NSTAT_MSG_TYPE_REM_SRC = 1003 222 | ,NSTAT_MSG_TYPE_QUERY_SRC = 1004 223 | ,NSTAT_MSG_TYPE_GET_SRC_DESC = 1005 224 | ,NSTAT_MSG_TYPE_SET_FILTER = 1006 225 | 226 | // Responses/Notfications 227 | ,NSTAT_MSG_TYPE_SRC_ADDED = 10001 228 | ,NSTAT_MSG_TYPE_SRC_REMOVED = 10002 229 | ,NSTAT_MSG_TYPE_SRC_DESC = 10003 230 | ,NSTAT_MSG_TYPE_SRC_COUNTS = 10004 231 | }; 232 | 233 | 234 | enum 235 | { 236 | NSTAT_SRC_REF_ALL = 0xffffffff 237 | ,NSTAT_SRC_REF_INVALID = 0 238 | }; 239 | 240 | enum 241 | { 242 | NSTAT_FILTER_NOZEROBYTES = 0x01, 243 | }; 244 | 245 | /* 246 | typedef struct nstat_msg_hdr 247 | { 248 | u_int64_t context; 249 | u_int32_t type; 250 | u_int32_t pad; // unused for now 251 | } nstat_msg_hdr; 252 | */ 253 | 254 | typedef struct nstat_msg_error 255 | { 256 | nstat_msg_hdr hdr; 257 | u_int32_t error; // errno error 258 | } nstat_msg_error; 259 | 260 | typedef struct nstat_msg_add_src 261 | { 262 | nstat_msg_hdr hdr; 263 | nstat_provider_id_t provider; 264 | u_int8_t param[]; 265 | } nstat_msg_add_src_req; 266 | 267 | typedef struct nstat_msg_add_all_srcs 268 | { 269 | nstat_msg_hdr hdr; 270 | nstat_provider_id_t provider; 271 | } nstat_msg_add_all_srcs; 272 | 273 | typedef struct nstat_msg_src_added 274 | { 275 | nstat_msg_hdr hdr; 276 | nstat_provider_id_t provider; 277 | nstat_src_ref_t srcref; 278 | } nstat_msg_src_added; 279 | 280 | typedef struct nstat_msg_rem_src 281 | { 282 | nstat_msg_hdr hdr; 283 | nstat_src_ref_t srcref; 284 | } nstat_msg_rem_src_req; 285 | 286 | typedef struct nstat_msg_get_src_description 287 | { 288 | nstat_msg_hdr hdr; 289 | nstat_src_ref_t srcref; 290 | } nstat_msg_get_src_description; 291 | 292 | typedef struct nstat_msg_set_filter 293 | { 294 | nstat_msg_hdr hdr; 295 | nstat_src_ref_t srcref; 296 | u_int32_t filter; 297 | } nstat_msg_set_filter; 298 | 299 | typedef struct nstat_msg_src_description 300 | { 301 | nstat_msg_hdr hdr; 302 | nstat_src_ref_t srcref; 303 | nstat_provider_id_t provider; 304 | u_int8_t data[]; 305 | } nstat_msg_src_description; 306 | 307 | typedef struct nstat_msg_query_src 308 | { 309 | nstat_msg_hdr hdr; 310 | nstat_src_ref_t srcref; 311 | } nstat_msg_query_src_req; 312 | 313 | typedef struct nstat_msg_src_counts 314 | { 315 | nstat_msg_hdr hdr; 316 | nstat_src_ref_t srcref; 317 | nstat_counts counts; 318 | } nstat_msg_src_counts; 319 | 320 | typedef struct nstat_msg_src_removed 321 | { 322 | nstat_msg_hdr hdr; 323 | nstat_src_ref_t srcref; 324 | } nstat_msg_src_removed; 325 | 326 | #pragma pack(pop) 327 | -------------------------------------------------------------------------------- /src/ntstat_kernel_2782.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "NTStatKernelStructHandler.hpp" 3 | 4 | // definitions from darwin-xnu/bsd/net/ntstat.h kernel header 5 | 6 | #include 7 | 8 | #include "ntstat_kernel_2782.h" 9 | 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class NTStatKernel2782 : public NTStatKernelStructHandler 16 | { 17 | public: 18 | virtual bool isProviderTcp(uint64_t providerId){ 19 | return (NSTAT_PROVIDER_TCP == providerId);} 20 | 21 | virtual bool isProviderUdp(uint64_t providerId) { 22 | return (NSTAT_PROVIDER_UDP == providerId);} 23 | 24 | virtual bool isProviderInterface(uint64_t providerId) { return NSTAT_PROVIDER_IFNET == providerId; } 25 | 26 | //-------------------------------------------------------------------- 27 | // write GET_SRC_DESC message to dest 28 | //-------------------------------------------------------------------- 29 | virtual void writeSrcDesc(MsgDest &dest, uint64_t providerId, uint64_t srcRef ) 30 | { 31 | nstat_msg_get_src_description msg = nstat_msg_get_src_description(); 32 | 33 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_GET_SRC_DESC); 34 | 35 | msg.srcref = (nstat_src_ref_t)srcRef; 36 | 37 | dest.send(&msg.hdr, sizeof(msg)); 38 | } 39 | 40 | //-------------------------------------------------------------------- 41 | // write QUERY_SRC message to dest 42 | //-------------------------------------------------------------------- 43 | virtual void writeQuerySrc(MsgDest &dest, uint64_t srcRef) 44 | { 45 | nstat_msg_query_src_req msg = nstat_msg_query_src_req(); 46 | 47 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_QUERY_SRC); 48 | 49 | msg.srcref= (nstat_src_ref_t)srcRef; 50 | 51 | dest.send(&msg.hdr, sizeof(msg)); 52 | } 53 | 54 | //-------------------------------------------------------------------- 55 | // write ADD_ADD_SRCS message to dest 56 | //-------------------------------------------------------------------- 57 | virtual void writeAddAllSrc(MsgDest &dest, uint32_t providerId) 58 | { 59 | nstat_msg_add_all_srcs msg = nstat_msg_add_all_srcs(); 60 | 61 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_ADD_ALL_SRCS); 62 | 63 | msg.provider = providerId ; 64 | 65 | dest.send(&msg.hdr, sizeof(msg)); 66 | } 67 | 68 | virtual void writeAddAllTcpSrc(MsgDest &dest) { 69 | writeAddAllSrc(dest, NSTAT_PROVIDER_TCP); 70 | } 71 | 72 | virtual void writeAddAllUdpSrc(MsgDest &dest) { 73 | writeAddAllSrc(dest, NSTAT_PROVIDER_UDP); 74 | } 75 | 76 | virtual void writeAddAllInterfaces(MsgDest &dest) { 77 | writeAddAllSrc(dest, NSTAT_PROVIDER_IFNET); 78 | } 79 | 80 | //-------------------------------------------------------------------- 81 | // extract srcRef, providerId (if possible) from message 82 | //-------------------------------------------------------------------- 83 | virtual void getSrcRef(nstat_msg_hdr* msg, int structlen, uint64_t &srcRef, uint32_t &providerId) { 84 | switch(msg->type) 85 | { 86 | case NSTAT_MSG_TYPE_SRC_COUNTS: 87 | srcRef = ((nstat_msg_src_counts*)msg)->srcref; 88 | break; 89 | case NSTAT_MSG_TYPE_SRC_DESC: 90 | srcRef = ((nstat_msg_src_description*)msg)->srcref; 91 | providerId = ((nstat_msg_src_description*)msg)->provider; 92 | break; 93 | case NSTAT_MSG_TYPE_SRC_ADDED: 94 | srcRef = ((nstat_msg_src_added*)msg)->srcref; 95 | providerId = ((nstat_msg_src_added*)msg)->provider; 96 | break; 97 | case NSTAT_MSG_TYPE_SRC_REMOVED: 98 | srcRef = ((nstat_msg_src_removed*)msg)->srcref; 99 | break; 100 | default: 101 | //printf("E getSrcRef not implemented for type %d\n", msg->type); 102 | break; 103 | } 104 | } 105 | 106 | 107 | 108 | //-------------------------------------------------------------------- 109 | // populate dest with message data 110 | //-------------------------------------------------------------------- 111 | virtual bool readSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 112 | { 113 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 114 | if (msg->provider == NSTAT_PROVIDER_TCP) { 115 | readTcpSrcDesc(hdr, structlen, dest); 116 | } else if (msg->provider == NSTAT_PROVIDER_UDP) { 117 | readUdpSrcDesc(hdr, structlen, dest); 118 | } else { 119 | // ?? 120 | return false; 121 | } 122 | return true; 123 | } 124 | 125 | //-------------------------------------------------------------------- 126 | // populate dest with message ifnet data 127 | //-------------------------------------------------------------------- 128 | /* 129 | virtual bool readSrcDesc(nstat_msg_hdr* hdr, int structlen, NTStatInterface* dest ) 130 | { 131 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 132 | if (msg->provider != NSTAT_PROVIDER_IFNET) return false; 133 | 134 | nstat_ifnet_descriptor* ifnet = (nstat_ifnet_descriptor*)msg->data; 135 | dest->name = string(ifnet->name); 136 | dest->description = string(ifnet->description); 137 | dest->ifindex = ifnet->ifindex; 138 | dest->type = ifnet->type; 139 | 140 | return false; 141 | }*/ 142 | 143 | //-------------------------------------------------------------------- 144 | // TCP: populate dest with message data 145 | //-------------------------------------------------------------------- 146 | virtual void readTcpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 147 | { 148 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 149 | nstat_tcp_descriptor*tcp = (nstat_tcp_descriptor*)msg->data; 150 | 151 | dest->key.ifindex = tcp->ifindex; 152 | dest->key.ipproto = IPPROTO_TCP; 153 | dest->key.isV6 = (tcp->local.v4.sin_family == AF_INET6); 154 | 155 | if (tcp->local.v4.sin_family == AF_INET6) 156 | { 157 | dest->key.lport = tcp->local.v6.sin6_port; 158 | dest->key.local.addr6 = tcp->local.v6.sin6_addr; 159 | dest->key.rport = tcp->remote.v6.sin6_port; 160 | dest->key.remote.addr6 = tcp->remote.v6.sin6_addr; 161 | } else { 162 | dest->key.lport = tcp->local.v4.sin_port; 163 | dest->key.rport = tcp->remote.v4.sin_port; 164 | dest->key.local.addr4 = tcp->local.v4.sin_addr; 165 | dest->key.remote.addr4 = tcp->remote.v4.sin_addr; 166 | } 167 | dest->states.txwindow = tcp->txwindow; 168 | dest->states.txcwindow = tcp->txcwindow; 169 | dest->states.state = tcp->state; 170 | 171 | dest->process.pid = tcp->pid; 172 | 173 | strcpy(dest->process.name, ((tcp->pid > 0 && tcp->pname[0]) ? tcp->pname : "")); 174 | } 175 | 176 | //-------------------------------------------------------------------- 177 | // UDP: populate dest with message data 178 | //-------------------------------------------------------------------- 179 | virtual void readUdpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 180 | { 181 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 182 | nstat_udp_descriptor*udp = (nstat_udp_descriptor*)msg->data; 183 | 184 | dest->key.ifindex = udp->ifindex; 185 | dest->key.ipproto = IPPROTO_UDP; 186 | dest->key.isV6 = (udp->local.v4.sin_family == AF_INET6); 187 | 188 | if (udp->local.v4.sin_family == AF_INET6) 189 | { 190 | dest->key.lport = udp->local.v6.sin6_port; 191 | dest->key.local.addr6 = udp->local.v6.sin6_addr; 192 | dest->key.rport = udp->remote.v6.sin6_port; 193 | dest->key.remote.addr6 = udp->remote.v6.sin6_addr; 194 | } else { 195 | dest->key.lport = udp->local.v4.sin_port; 196 | dest->key.rport = udp->remote.v4.sin_port; 197 | dest->key.local.addr4 = udp->local.v4.sin_addr; 198 | dest->key.remote.addr4 = udp->remote.v4.sin_addr; 199 | } 200 | 201 | dest->process.pid = udp->pid; 202 | strcpy(dest->process.name, ((udp->pid > 0 && udp->pname[0]) ? udp->pname : "")); 203 | } 204 | 205 | //-------------------------------------------------------------------- 206 | // populate dest with message counts data 207 | //-------------------------------------------------------------------- 208 | virtual void readCounts(nstat_msg_hdr*hdr, int structlen, NTStatCounters& dest ) 209 | { 210 | nstat_msg_src_counts *msg = (nstat_msg_src_counts*)hdr; 211 | dest.rxbytes = msg->counts.nstat_rxbytes; 212 | dest.txbytes = msg->counts.nstat_txbytes; 213 | dest.rxpackets = msg->counts.nstat_rxpackets; 214 | dest.txpackets = msg->counts.nstat_txpackets; 215 | 216 | dest.cell_rxbytes = msg->counts.nstat_cell_rxbytes; 217 | dest.cell_txbytes = msg->counts.nstat_cell_txbytes; 218 | 219 | dest.wifi_rxbytes = msg->counts.nstat_wifi_rxbytes; 220 | dest.wifi_txbytes = msg->counts.nstat_wifi_txbytes; 221 | 222 | dest.wired_rxbytes = msg->counts.nstat_wired_rxbytes; 223 | dest.wired_txbytes = msg->counts.nstat_wired_txbytes; 224 | } 225 | 226 | }; 227 | 228 | 229 | NTStatKernelStructHandler* NewNTStatKernel2782() { 230 | return new NTStatKernel2782(); 231 | } 232 | -------------------------------------------------------------------------------- /src/ntstat_kernel_2782.h: -------------------------------------------------------------------------------- 1 | // https://github.com/apple/darwin-xnu 2 | // git checkout xnu-2782.40.9 3 | // Yosemite 10.10 4 | 5 | // bsd/netinet/tcp.h 6 | struct tcp_conn_status { 7 | unsigned int probe_activated : 1; 8 | unsigned int write_probe_failed : 1; 9 | unsigned int read_probe_failed : 1; 10 | unsigned int conn_probe_failed : 1; 11 | }; 12 | #define IFNAMSIZ 16 13 | 14 | // bsd/net/ntstat.h 15 | 16 | #pragma pack(push, 4) 17 | 18 | #define __NSTAT_REVISION__ 6 19 | 20 | typedef u_int32_t nstat_provider_id_t; 21 | typedef u_int32_t nstat_src_ref_t; 22 | 23 | typedef struct nstat_counts 24 | { 25 | /* Counters */ 26 | u_int64_t nstat_rxpackets __attribute__((aligned(8))); 27 | u_int64_t nstat_rxbytes __attribute__((aligned(8))); 28 | u_int64_t nstat_txpackets __attribute__((aligned(8))); 29 | u_int64_t nstat_txbytes __attribute__((aligned(8))); 30 | 31 | u_int32_t nstat_rxduplicatebytes; 32 | u_int32_t nstat_rxoutoforderbytes; 33 | u_int32_t nstat_txretransmit; 34 | 35 | u_int32_t nstat_connectattempts; 36 | u_int32_t nstat_connectsuccesses; 37 | 38 | u_int32_t nstat_min_rtt; 39 | u_int32_t nstat_avg_rtt; 40 | u_int32_t nstat_var_rtt; 41 | 42 | u_int64_t nstat_cell_rxbytes __attribute__((aligned(8))); 43 | u_int64_t nstat_cell_txbytes __attribute__((aligned(8))); 44 | u_int64_t nstat_wifi_rxbytes __attribute__((aligned(8))); 45 | u_int64_t nstat_wifi_txbytes __attribute__((aligned(8))); 46 | u_int64_t nstat_wired_rxbytes __attribute__((aligned(8))); 47 | u_int64_t nstat_wired_txbytes __attribute__((aligned(8))); 48 | } nstat_counts; 49 | 50 | typedef struct nstat_sysinfo_keyval 51 | { 52 | u_int32_t nstat_sysinfo_key; 53 | u_int32_t nstat_sysinfo_flags; 54 | union { 55 | int64_t nstat_sysinfo_scalar; 56 | double nstat_sysinfo_distribution; 57 | } u; 58 | } nstat_sysinfo_keyval; 59 | 60 | #define NSTAT_SYSINFO_FLAG_SCALAR 0x0001 61 | #define NSTAT_SYSINFO_FLAG_DISTRIBUTION 0x0002 62 | 63 | typedef struct nstat_sysinfo_counts 64 | { 65 | /* Counters */ 66 | u_int32_t nstat_sysinfo_len; 67 | u_int32_t pad; 68 | u_int8_t nstat_sysinfo_keyvals[]; 69 | } nstat_sysinfo_counts; 70 | 71 | enum 72 | { 73 | NSTAT_SYSINFO_KEY_MBUF_256B_TOTAL = 1 74 | ,NSTAT_SYSINFO_KEY_MBUF_2KB_TOTAL = 2 75 | ,NSTAT_SYSINFO_KEY_MBUF_4KB_TOTAL = 3 76 | ,NSTAT_SYSINFO_KEY_SOCK_MBCNT = 4 77 | ,NSTAT_SYSINFO_KEY_SOCK_ATMBLIMIT = 5 78 | ,NSTAT_SYSINFO_KEY_IPV4_AVGRTT = 6 79 | ,NSTAT_SYSINFO_KEY_IPV6_AVGRTT = 7 80 | ,NSTAT_SYSINFO_KEY_SEND_PLR = 8 81 | ,NSTAT_SYSINFO_KEY_RECV_PLR = 9 82 | ,NSTAT_SYSINFO_KEY_SEND_TLRTO = 10 83 | ,NSTAT_SYSINFO_KEY_SEND_REORDERRATE = 11 84 | 85 | }; 86 | 87 | #pragma mark -- Network Statistics Providers -- 88 | 89 | enum 90 | { 91 | NSTAT_PROVIDER_ROUTE = 1 92 | ,NSTAT_PROVIDER_TCP = 2 93 | ,NSTAT_PROVIDER_UDP = 3 94 | ,NSTAT_PROVIDER_IFNET = 4 95 | ,NSTAT_PROVIDER_SYSINFO = 5 96 | }; 97 | 98 | typedef struct nstat_route_add_param 99 | { 100 | union 101 | { 102 | struct sockaddr_in v4; 103 | struct sockaddr_in6 v6; 104 | } dst; 105 | union 106 | { 107 | struct sockaddr_in v4; 108 | struct sockaddr_in6 v6; 109 | } mask; 110 | u_int32_t ifindex; 111 | } nstat_route_add_param; 112 | 113 | typedef struct nstat_tcp_add_param 114 | { 115 | union 116 | { 117 | struct sockaddr_in v4; 118 | struct sockaddr_in6 v6; 119 | } local; 120 | union 121 | { 122 | struct sockaddr_in v4; 123 | struct sockaddr_in6 v6; 124 | } remote; 125 | } nstat_tcp_add_param; 126 | 127 | typedef struct nstat_tcp_descriptor 128 | { 129 | union 130 | { 131 | struct sockaddr_in v4; 132 | struct sockaddr_in6 v6; 133 | } local; 134 | 135 | union 136 | { 137 | struct sockaddr_in v4; 138 | struct sockaddr_in6 v6; 139 | } remote; 140 | 141 | u_int32_t ifindex; 142 | 143 | u_int32_t state; 144 | 145 | u_int32_t sndbufsize; 146 | u_int32_t sndbufused; 147 | u_int32_t rcvbufsize; 148 | u_int32_t rcvbufused; 149 | u_int32_t txunacked; 150 | u_int32_t txwindow; 151 | u_int32_t txcwindow; 152 | u_int32_t traffic_class; 153 | u_int32_t traffic_mgt_flags; 154 | char cc_algo[16]; 155 | 156 | u_int64_t upid; 157 | u_int32_t pid; 158 | char pname[64]; 159 | u_int64_t eupid; 160 | u_int32_t epid; 161 | 162 | uint8_t uuid[16]; 163 | uint8_t euuid[16]; 164 | uint8_t vuuid[16]; 165 | } nstat_tcp_descriptor; 166 | 167 | typedef struct nstat_tcp_add_param nstat_udp_add_param; 168 | 169 | typedef struct nstat_udp_descriptor 170 | { 171 | union 172 | { 173 | struct sockaddr_in v4; 174 | struct sockaddr_in6 v6; 175 | } local; 176 | 177 | union 178 | { 179 | struct sockaddr_in v4; 180 | struct sockaddr_in6 v6; 181 | } remote; 182 | 183 | u_int32_t ifindex; 184 | 185 | u_int32_t rcvbufsize; 186 | u_int32_t rcvbufused; 187 | u_int32_t traffic_class; 188 | 189 | u_int64_t upid; 190 | u_int32_t pid; 191 | char pname[64]; 192 | u_int64_t eupid; 193 | u_int32_t epid; 194 | 195 | uint8_t uuid[16]; 196 | uint8_t euuid[16]; 197 | uint8_t vuuid[16]; 198 | } nstat_udp_descriptor; 199 | 200 | typedef struct nstat_route_descriptor 201 | { 202 | u_int64_t id; 203 | u_int64_t parent_id; 204 | u_int64_t gateway_id; 205 | 206 | union 207 | { 208 | struct sockaddr_in v4; 209 | struct sockaddr_in6 v6; 210 | struct sockaddr sa; 211 | } dst; 212 | 213 | union 214 | { 215 | struct sockaddr_in v4; 216 | struct sockaddr_in6 v6; 217 | struct sockaddr sa; 218 | } mask; 219 | 220 | union 221 | { 222 | struct sockaddr_in v4; 223 | struct sockaddr_in6 v6; 224 | struct sockaddr sa; 225 | } gateway; 226 | 227 | u_int32_t ifindex; 228 | u_int32_t flags; 229 | 230 | } nstat_route_descriptor; 231 | 232 | typedef struct nstat_ifnet_add_param 233 | { 234 | u_int32_t ifindex; 235 | u_int64_t threshold; 236 | } nstat_ifnet_add_param; 237 | 238 | #ifndef IF_DESCSIZE 239 | #define IF_DESCSIZE 128 240 | #endif 241 | typedef struct nstat_ifnet_descriptor 242 | { 243 | char name[IFNAMSIZ+1]; 244 | u_int32_t ifindex; 245 | u_int64_t threshold; 246 | unsigned int type; 247 | char description[IF_DESCSIZE]; 248 | } nstat_ifnet_descriptor; 249 | 250 | typedef struct nstat_sysinfo_descriptor 251 | { 252 | u_int32_t flags; 253 | } nstat_sysinfo_descriptor; 254 | 255 | typedef struct nstat_sysinfo_add_param 256 | { 257 | /* To indicate which system level information should be collected */ 258 | u_int32_t flags; 259 | } nstat_sysinfo_add_param; 260 | 261 | #define NSTAT_SYSINFO_MBUF_STATS 0x0001 262 | #define NSTAT_SYSINFO_TCP_STATS 0x0002 263 | 264 | #pragma mark -- Network Statistics User Client -- 265 | 266 | #define NET_STAT_CONTROL_NAME "com.apple.network.statistics" 267 | 268 | enum 269 | { 270 | // generic response messages 271 | NSTAT_MSG_TYPE_SUCCESS = 0 272 | ,NSTAT_MSG_TYPE_ERROR = 1 273 | 274 | // Requests 275 | ,NSTAT_MSG_TYPE_ADD_SRC = 1001 276 | ,NSTAT_MSG_TYPE_ADD_ALL_SRCS = 1002 277 | ,NSTAT_MSG_TYPE_REM_SRC = 1003 278 | ,NSTAT_MSG_TYPE_QUERY_SRC = 1004 279 | ,NSTAT_MSG_TYPE_GET_SRC_DESC = 1005 280 | ,NSTAT_MSG_TYPE_SET_FILTER = 1006 281 | 282 | // Responses/Notfications 283 | ,NSTAT_MSG_TYPE_SRC_ADDED = 10001 284 | ,NSTAT_MSG_TYPE_SRC_REMOVED = 10002 285 | ,NSTAT_MSG_TYPE_SRC_DESC = 10003 286 | ,NSTAT_MSG_TYPE_SRC_COUNTS = 10004 287 | ,NSTAT_MSG_TYPE_SYSINFO_COUNTS = 10005 288 | }; 289 | 290 | enum 291 | { 292 | NSTAT_SRC_REF_ALL = 0xffffffff 293 | ,NSTAT_SRC_REF_INVALID = 0 294 | }; 295 | 296 | enum 297 | { 298 | NSTAT_FILTER_NOZEROBYTES = 0x01, 299 | }; 300 | /* 301 | typedef struct nstat_msg_hdr 302 | { 303 | u_int64_t context; 304 | u_int32_t type; 305 | u_int32_t pad; // unused for now 306 | } nstat_msg_hdr; 307 | */ 308 | 309 | typedef struct nstat_msg_error 310 | { 311 | nstat_msg_hdr hdr; 312 | u_int32_t error; // errno error 313 | } nstat_msg_error; 314 | 315 | typedef struct nstat_msg_add_src 316 | { 317 | nstat_msg_hdr hdr; 318 | nstat_provider_id_t provider; 319 | u_int8_t param[]; 320 | } nstat_msg_add_src_req; 321 | 322 | typedef struct nstat_msg_add_all_srcs 323 | { 324 | nstat_msg_hdr hdr; 325 | nstat_provider_id_t provider; 326 | } nstat_msg_add_all_srcs; 327 | 328 | typedef struct nstat_msg_src_added 329 | { 330 | nstat_msg_hdr hdr; 331 | nstat_provider_id_t provider; 332 | nstat_src_ref_t srcref; 333 | } nstat_msg_src_added; 334 | 335 | typedef struct nstat_msg_rem_src 336 | { 337 | nstat_msg_hdr hdr; 338 | nstat_src_ref_t srcref; 339 | } nstat_msg_rem_src_req; 340 | 341 | typedef struct nstat_msg_get_src_description 342 | { 343 | nstat_msg_hdr hdr; 344 | nstat_src_ref_t srcref; 345 | } nstat_msg_get_src_description; 346 | 347 | typedef struct nstat_msg_set_filter 348 | { 349 | nstat_msg_hdr hdr; 350 | nstat_src_ref_t srcref; 351 | u_int32_t filter; 352 | } nstat_msg_set_filter; 353 | 354 | typedef struct nstat_msg_src_description 355 | { 356 | nstat_msg_hdr hdr; 357 | nstat_src_ref_t srcref; 358 | nstat_provider_id_t provider; 359 | u_int8_t data[]; 360 | } nstat_msg_src_description; 361 | 362 | typedef struct nstat_msg_query_src 363 | { 364 | nstat_msg_hdr hdr; 365 | nstat_src_ref_t srcref; 366 | } nstat_msg_query_src_req; 367 | 368 | typedef struct nstat_msg_src_counts 369 | { 370 | nstat_msg_hdr hdr; 371 | nstat_src_ref_t srcref; 372 | nstat_counts counts; 373 | } nstat_msg_src_counts; 374 | 375 | typedef struct nstat_msg_src_removed 376 | { 377 | nstat_msg_hdr hdr; 378 | nstat_src_ref_t srcref; 379 | } nstat_msg_src_removed; 380 | 381 | typedef struct nstat_msg_sysinfo_counts 382 | { 383 | nstat_msg_hdr hdr; 384 | nstat_src_ref_t srcref; 385 | nstat_sysinfo_counts counts; 386 | } nstat_msg_sysinfo_counts; 387 | 388 | typedef struct nstat_sysinfo_mbuf_stats 389 | { 390 | u_int32_t total_256b; 391 | u_int32_t total_2kb; 392 | u_int32_t total_4kb; 393 | u_int32_t sbmb_total; 394 | u_int32_t sb_atmbuflimit; 395 | u_int32_t draincnt; 396 | u_int32_t memreleased; 397 | } nstat_sysinfo_mbuf_stats; 398 | 399 | typedef struct nstat_sysinfo_tcp_stats 400 | { 401 | u_int32_t ipv4_avgrtt; 402 | u_int32_t ipv6_avgrtt; 403 | u_int32_t send_plr; 404 | u_int32_t recv_plr; 405 | u_int32_t send_tlrto_rate; 406 | u_int32_t send_reorder_rate; 407 | } nstat_sysinfo_tcp_stats; 408 | 409 | typedef struct nstat_sysinfo_data 410 | { 411 | u_int32_t flags; 412 | union { 413 | nstat_sysinfo_mbuf_stats mb_stats; 414 | nstat_sysinfo_tcp_stats tcp_stats; 415 | } u; 416 | } nstat_sysinfo_data; 417 | 418 | #pragma pack(pop) 419 | -------------------------------------------------------------------------------- /src/ntstat_kernel_3248.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "NTStatKernelStructHandler.hpp" 3 | 4 | // definitions from darwin-xnu/bsd/net/ntstat.h kernel header 5 | 6 | #include 7 | 8 | #include "ntstat_kernel_3248.h" 9 | 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class NTStatKernel3248 : public NTStatKernelStructHandler 16 | { 17 | public: 18 | 19 | virtual bool isProviderTcp(uint64_t providerId){ 20 | return (NSTAT_PROVIDER_TCP == providerId);} 21 | 22 | virtual bool isProviderUdp(uint64_t providerId) { 23 | return (NSTAT_PROVIDER_UDP == providerId);} 24 | 25 | virtual bool isProviderInterface(uint64_t providerId) { return NSTAT_PROVIDER_IFNET == providerId; } 26 | 27 | //-------------------------------------------------------------------- 28 | // write GET_SRC_DESC message to dest 29 | //-------------------------------------------------------------------- 30 | virtual void writeSrcDesc(MsgDest &dest, uint64_t providerId, uint64_t srcRef ) 31 | { 32 | nstat_msg_get_src_description msg = nstat_msg_get_src_description(); 33 | 34 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_GET_SRC_DESC); 35 | 36 | msg.srcref = (nstat_src_ref_t)srcRef; 37 | 38 | dest.send(&msg.hdr, sizeof(msg)); 39 | } 40 | 41 | //-------------------------------------------------------------------- 42 | // write QUERY_SRC message to dest 43 | //-------------------------------------------------------------------- 44 | virtual void writeQuerySrc(MsgDest &dest, uint64_t srcRef) 45 | { 46 | nstat_msg_query_src_req msg = nstat_msg_query_src_req(); 47 | 48 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_QUERY_SRC); 49 | 50 | msg.srcref= (nstat_src_ref_t)srcRef; 51 | 52 | dest.send(&msg.hdr, sizeof(msg)); 53 | } 54 | 55 | //-------------------------------------------------------------------- 56 | // write ADD_ADD_SRCS message to dest 57 | //-------------------------------------------------------------------- 58 | virtual void writeAddAllSrc(MsgDest &dest, uint32_t providerId) 59 | { 60 | nstat_msg_add_all_srcs msg = nstat_msg_add_all_srcs(); 61 | 62 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_ADD_ALL_SRCS); 63 | 64 | msg.provider = providerId ; 65 | 66 | dest.send(&msg.hdr, sizeof(msg)); 67 | } 68 | 69 | // xnu-3789 is first time we see split _KERNEL and _USERLAND 70 | 71 | virtual void writeAddAllTcpSrc(MsgDest &dest) { 72 | writeAddAllSrc(dest, NSTAT_PROVIDER_TCP); 73 | } 74 | 75 | virtual void writeAddAllUdpSrc(MsgDest &dest) { 76 | writeAddAllSrc(dest, NSTAT_PROVIDER_UDP); 77 | } 78 | 79 | virtual void writeAddAllInterfaces(MsgDest &dest) { 80 | writeAddAllSrc(dest, NSTAT_PROVIDER_IFNET); 81 | } 82 | 83 | //-------------------------------------------------------------------- 84 | // extract srcRef, providerId (if possible) from message 85 | //-------------------------------------------------------------------- 86 | virtual void getSrcRef(nstat_msg_hdr* msg, int structlen, uint64_t &srcRef, uint32_t &providerId) { 87 | switch(msg->type) 88 | { 89 | case NSTAT_MSG_TYPE_SRC_COUNTS: 90 | srcRef = ((nstat_msg_src_counts*)msg)->srcref; 91 | break; 92 | case NSTAT_MSG_TYPE_SRC_DESC: 93 | srcRef = ((nstat_msg_src_description*)msg)->srcref; 94 | providerId = ((nstat_msg_src_description*)msg)->provider; 95 | break; 96 | case NSTAT_MSG_TYPE_SRC_ADDED: 97 | srcRef = ((nstat_msg_src_added*)msg)->srcref; 98 | providerId = ((nstat_msg_src_added*)msg)->provider; 99 | break; 100 | case NSTAT_MSG_TYPE_SRC_REMOVED: 101 | srcRef = ((nstat_msg_src_removed*)msg)->srcref; 102 | break; 103 | case NSTAT_MSG_TYPE_QUERY_SRC: 104 | srcRef = ((nstat_msg_query_src*)msg)->srcref; 105 | break; 106 | case NSTAT_MSG_TYPE_GET_SRC_DESC: 107 | srcRef = ((nstat_msg_get_src_description*)msg)->srcref; 108 | break; 109 | case NSTAT_MSG_TYPE_REM_SRC: 110 | srcRef = ((nstat_msg_rem_src*)msg)->srcref; 111 | break; 112 | default: 113 | //printf("E getSrcRef not implemented for type %d\n", msg->type); 114 | break; 115 | } 116 | } 117 | 118 | 119 | //-------------------------------------------------------------------- 120 | // populate dest with message data 121 | //-------------------------------------------------------------------- 122 | virtual bool readSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 123 | { 124 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 125 | if (msg->provider == NSTAT_PROVIDER_TCP) { 126 | readTcpSrcDesc(hdr, structlen, dest); 127 | } else if (msg->provider == NSTAT_PROVIDER_UDP) { 128 | readUdpSrcDesc(hdr, structlen, dest); 129 | } else { 130 | // ?? 131 | return false; 132 | } 133 | return true; 134 | } 135 | 136 | 137 | //-------------------------------------------------------------------- 138 | // populate dest with message ifnet data 139 | //-------------------------------------------------------------------- 140 | /* 141 | virtual bool readSrcDesc(nstat_msg_hdr* hdr, int structlen, NTStatInterface* dest ) 142 | { 143 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 144 | if (msg->provider != NSTAT_PROVIDER_IFNET) return false; 145 | 146 | nstat_ifnet_descriptor* ifnet = (nstat_ifnet_descriptor*)msg->data; 147 | dest->name = string(ifnet->name); 148 | dest->description = string(ifnet->description); 149 | dest->ifindex = ifnet->ifindex; 150 | dest->type = ifnet->type; 151 | 152 | return false; 153 | }*/ 154 | 155 | //-------------------------------------------------------------------- 156 | // TCP: populate dest with message data 157 | //-------------------------------------------------------------------- 158 | virtual void readTcpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 159 | { 160 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 161 | nstat_tcp_descriptor*tcp = (nstat_tcp_descriptor*)msg->data; 162 | 163 | dest->key.ifindex = tcp->ifindex; 164 | dest->key.ipproto = IPPROTO_TCP; 165 | dest->key.isV6 = (tcp->local.v4.sin_family == AF_INET6); 166 | 167 | if (tcp->local.v4.sin_family == AF_INET6) 168 | { 169 | dest->key.lport = tcp->local.v6.sin6_port; 170 | dest->key.local.addr6 = tcp->local.v6.sin6_addr; 171 | dest->key.rport = tcp->remote.v6.sin6_port; 172 | dest->key.remote.addr6 = tcp->remote.v6.sin6_addr; 173 | } else { 174 | dest->key.lport = tcp->local.v4.sin_port; 175 | dest->key.rport = tcp->remote.v4.sin_port; 176 | dest->key.local.addr4 = tcp->local.v4.sin_addr; 177 | dest->key.remote.addr4 = tcp->remote.v4.sin_addr; 178 | } 179 | dest->states.txwindow = tcp->txwindow; 180 | dest->states.txcwindow = tcp->txcwindow; 181 | dest->states.state = tcp->state; 182 | 183 | dest->process.pid = tcp->pid; 184 | 185 | strcpy(dest->process.name, ((tcp->pid > 0 && tcp->pname[0]) ? tcp->pname : "")); 186 | } 187 | 188 | //-------------------------------------------------------------------- 189 | // UDP: populate dest with message data 190 | //-------------------------------------------------------------------- 191 | virtual void readUdpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 192 | { 193 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 194 | nstat_udp_descriptor*udp = (nstat_udp_descriptor*)msg->data; 195 | 196 | dest->key.ifindex = udp->ifindex; 197 | dest->key.ipproto = IPPROTO_UDP; 198 | dest->key.isV6 = (udp->local.v4.sin_family == AF_INET6); 199 | 200 | if (udp->local.v4.sin_family == AF_INET6) 201 | { 202 | dest->key.lport = udp->local.v6.sin6_port; 203 | dest->key.local.addr6 = udp->local.v6.sin6_addr; 204 | dest->key.rport = udp->remote.v6.sin6_port; 205 | dest->key.remote.addr6 = udp->remote.v6.sin6_addr; 206 | } else { 207 | dest->key.lport = udp->local.v4.sin_port; 208 | dest->key.rport = udp->remote.v4.sin_port; 209 | dest->key.local.addr4 = udp->local.v4.sin_addr; 210 | dest->key.remote.addr4 = udp->remote.v4.sin_addr; 211 | } 212 | 213 | dest->process.pid = udp->pid; 214 | strcpy(dest->process.name, ((udp->pid > 0 && udp->pname[0]) ? udp->pname : "")); 215 | } 216 | 217 | //-------------------------------------------------------------------- 218 | // populate dest with message counts data 219 | //-------------------------------------------------------------------- 220 | virtual void readCounts(nstat_msg_hdr*hdr, int structlen, NTStatCounters& dest ) 221 | { 222 | nstat_msg_src_counts *msg = (nstat_msg_src_counts*)hdr; 223 | dest.rxbytes = msg->counts.nstat_rxbytes; 224 | dest.txbytes = msg->counts.nstat_txbytes; 225 | dest.rxpackets = msg->counts.nstat_rxpackets; 226 | dest.txpackets = msg->counts.nstat_txpackets; 227 | 228 | dest.cell_rxbytes = msg->counts.nstat_cell_rxbytes; 229 | dest.cell_txbytes = msg->counts.nstat_cell_txbytes; 230 | 231 | dest.wifi_rxbytes = msg->counts.nstat_wifi_rxbytes; 232 | dest.wifi_txbytes = msg->counts.nstat_wifi_txbytes; 233 | 234 | dest.wired_rxbytes = msg->counts.nstat_wired_rxbytes; 235 | dest.wired_txbytes = msg->counts.nstat_wired_txbytes; 236 | } 237 | 238 | }; 239 | 240 | 241 | NTStatKernelStructHandler* NewNTStatKernel3248() { 242 | return new NTStatKernel3248(); 243 | } 244 | -------------------------------------------------------------------------------- /src/ntstat_kernel_3248.h: -------------------------------------------------------------------------------- 1 | // definitions from bsd/net/ntstat.h kernel header 2 | // https://github.com/apple/darwin-xnu 3 | // git checkout xnu-3248.60.10 4 | // El Capitan 10.11 5 | 6 | // bsd/netinet/tcp.h 7 | struct tcp_conn_status { 8 | unsigned int probe_activated : 1; 9 | unsigned int write_probe_failed : 1; 10 | unsigned int read_probe_failed : 1; 11 | unsigned int conn_probe_failed : 1; 12 | }; 13 | #define IFNAMSIZ 16 14 | 15 | #pragma pack(push, 4) 16 | #pragma mark -- Common Data Structures -- 17 | 18 | #define __NSTAT_REVISION__ 7 19 | 20 | typedef u_int32_t nstat_provider_id_t; 21 | typedef u_int32_t nstat_src_ref_t; 22 | 23 | typedef struct nstat_counts 24 | { 25 | /* Counters */ 26 | u_int64_t nstat_rxpackets __attribute__((aligned(8))); 27 | u_int64_t nstat_rxbytes __attribute__((aligned(8))); 28 | u_int64_t nstat_txpackets __attribute__((aligned(8))); 29 | u_int64_t nstat_txbytes __attribute__((aligned(8))); 30 | 31 | u_int32_t nstat_rxduplicatebytes; 32 | u_int32_t nstat_rxoutoforderbytes; 33 | u_int32_t nstat_txretransmit; 34 | 35 | u_int32_t nstat_connectattempts; 36 | u_int32_t nstat_connectsuccesses; 37 | 38 | u_int32_t nstat_min_rtt; 39 | u_int32_t nstat_avg_rtt; 40 | u_int32_t nstat_var_rtt; 41 | 42 | u_int64_t nstat_cell_rxbytes __attribute__((aligned(8))); 43 | u_int64_t nstat_cell_txbytes __attribute__((aligned(8))); 44 | u_int64_t nstat_wifi_rxbytes __attribute__((aligned(8))); 45 | u_int64_t nstat_wifi_txbytes __attribute__((aligned(8))); 46 | u_int64_t nstat_wired_rxbytes __attribute__((aligned(8))); 47 | u_int64_t nstat_wired_txbytes __attribute__((aligned(8))); 48 | } nstat_counts; 49 | 50 | typedef struct nstat_sysinfo_keyval 51 | { 52 | u_int32_t nstat_sysinfo_key; 53 | u_int32_t nstat_sysinfo_flags; 54 | union { 55 | int64_t nstat_sysinfo_scalar; 56 | double nstat_sysinfo_distribution; 57 | } u; 58 | } __attribute__((packed)) nstat_sysinfo_keyval; 59 | 60 | #define NSTAT_SYSINFO_FLAG_SCALAR 0x0001 61 | #define NSTAT_SYSINFO_FLAG_DISTRIBUTION 0x0002 62 | 63 | #define NSTAT_MAX_MSG_SIZE 4096 64 | 65 | typedef struct nstat_sysinfo_counts 66 | { 67 | /* Counters */ 68 | u_int32_t nstat_sysinfo_len; 69 | u_int32_t pad; 70 | u_int8_t nstat_sysinfo_keyvals[]; 71 | } __attribute__((packed)) nstat_sysinfo_counts; 72 | 73 | enum 74 | { 75 | NSTAT_SYSINFO_KEY_MBUF_256B_TOTAL = 1 76 | ,NSTAT_SYSINFO_KEY_MBUF_2KB_TOTAL = 2 77 | ,NSTAT_SYSINFO_KEY_MBUF_4KB_TOTAL = 3 78 | ,NSTAT_SYSINFO_KEY_SOCK_MBCNT = 4 79 | ,NSTAT_SYSINFO_KEY_SOCK_ATMBLIMIT = 5 80 | ,NSTAT_SYSINFO_KEY_IPV4_AVGRTT = 6 81 | ,NSTAT_SYSINFO_KEY_IPV6_AVGRTT = 7 82 | ,NSTAT_SYSINFO_KEY_SEND_PLR = 8 83 | ,NSTAT_SYSINFO_KEY_RECV_PLR = 9 84 | ,NSTAT_SYSINFO_KEY_SEND_TLRTO = 10 85 | ,NSTAT_SYSINFO_KEY_SEND_REORDERRATE = 11 86 | ,NSTAT_SYSINFO_CONNECTION_ATTEMPTS = 12 87 | ,NSTAT_SYSINFO_CONNECTION_ACCEPTS = 13 88 | ,NSTAT_SYSINFO_ECN_CLIENT_SETUP = 14 89 | ,NSTAT_SYSINFO_ECN_SERVER_SETUP = 15 90 | ,NSTAT_SYSINFO_ECN_CLIENT_SUCCESS = 16 91 | ,NSTAT_SYSINFO_ECN_SERVER_SUCCESS = 17 92 | ,NSTAT_SYSINFO_ECN_NOT_SUPPORTED = 18 93 | ,NSTAT_SYSINFO_ECN_LOST_SYN = 19 94 | ,NSTAT_SYSINFO_ECN_LOST_SYNACK = 20 95 | ,NSTAT_SYSINFO_ECN_RECV_CE = 21 96 | ,NSTAT_SYSINFO_ECN_RECV_ECE = 22 97 | ,NSTAT_SYSINFO_ECN_SENT_ECE = 23 98 | ,NSTAT_SYSINFO_ECN_CONN_RECV_CE = 24 99 | ,NSTAT_SYSINFO_ECN_CONN_PLNOCE = 25 100 | ,NSTAT_SYSINFO_ECN_CONN_PL_CE = 26 101 | ,NSTAT_SYSINFO_ECN_CONN_NOPL_CE = 27 102 | ,NSTAT_SYSINFO_MBUF_16KB_TOTAL = 28 103 | ,NSTAT_SYSINFO_ECN_CLIENT_ENABLED = 29 104 | ,NSTAT_SYSINFO_ECN_SERVER_ENABLED = 30 105 | ,NSTAT_SYSINFO_ECN_CONN_RECV_ECE = 31 106 | ,NSTAT_SYSINFO_MBUF_MEM_RELEASED = 32 107 | ,NSTAT_SYSINFO_MBUF_DRAIN_CNT = 33 108 | ,NSTAT_SYSINFO_TFO_SYN_DATA_RCV = 34 109 | ,NSTAT_SYSINFO_TFO_COOKIE_REQ_RCV = 35 110 | ,NSTAT_SYSINFO_TFO_COOKIE_SENT = 36 111 | ,NSTAT_SYSINFO_TFO_COOKIE_INVALID = 37 112 | ,NSTAT_SYSINFO_TFO_COOKIE_REQ = 38 113 | ,NSTAT_SYSINFO_TFO_COOKIE_RCV = 39 114 | ,NSTAT_SYSINFO_TFO_SYN_DATA_SENT = 40 115 | ,NSTAT_SYSINFO_TFO_SYN_DATA_ACKED = 41 116 | ,NSTAT_SYSINFO_TFO_SYN_LOSS = 42 117 | ,NSTAT_SYSINFO_TFO_BLACKHOLE = 43 118 | ,NSTAT_SYSINFO_ECN_FALLBACK_SYNLOSS = 44 119 | ,NSTAT_SYSINFO_ECN_FALLBACK_REORDER = 45 120 | ,NSTAT_SYSINFO_ECN_FALLBACK_CE = 46 121 | ,NSTAT_SYSINFO_ECN_IFNET_TYPE = 47 122 | ,NSTAT_SYSINFO_ECN_IFNET_PROTO = 48 123 | ,NSTAT_SYSINFO_ECN_IFNET_CLIENT_SETUP = 49 124 | ,NSTAT_SYSINFO_ECN_IFNET_SERVER_SETUP = 50 125 | ,NSTAT_SYSINFO_ECN_IFNET_CLIENT_SUCCESS = 51 126 | ,NSTAT_SYSINFO_ECN_IFNET_SERVER_SUCCESS = 52 127 | ,NSTAT_SYSINFO_ECN_IFNET_PEER_NOSUPPORT = 53 128 | ,NSTAT_SYSINFO_ECN_IFNET_SYN_LOST = 54 129 | ,NSTAT_SYSINFO_ECN_IFNET_SYNACK_LOST = 55 130 | ,NSTAT_SYSINFO_ECN_IFNET_RECV_CE = 56 131 | ,NSTAT_SYSINFO_ECN_IFNET_RECV_ECE = 57 132 | ,NSTAT_SYSINFO_ECN_IFNET_SENT_ECE = 58 133 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_RECV_CE = 59 134 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_RECV_ECE = 60 135 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_PLNOCE = 61 136 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_PLCE = 62 137 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_NOPLCE = 63 138 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_SYNLOSS = 64 139 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_REORDER = 65 140 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_CE = 66 141 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RTT_AVG = 67 142 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RTT_VAR = 68 143 | ,NSTAT_SYSINFO_ECN_IFNET_ON_OOPERCENT = 69 144 | ,NSTAT_SYSINFO_ECN_IFNET_ON_SACK_EPISODE = 70 145 | ,NSTAT_SYSINFO_ECN_IFNET_ON_REORDER_PERCENT = 71 146 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RXMIT_PERCENT = 72 147 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RXMIT_DROP = 73 148 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RTT_AVG = 74 149 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RTT_VAR = 75 150 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_OOPERCENT = 76 151 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_SACK_EPISODE = 77 152 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_REORDER_PERCENT = 78 153 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RXMIT_PERCENT = 79 154 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RXMIT_DROP = 80 155 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_TXPKTS = 81 156 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_RXMTPKTS = 82 157 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_RXPKTS = 83 158 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_OOPKTS = 84 159 | ,NSTAT_SYSINFO_ECN_IFNET_ON_DROP_RST = 85 160 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_TXPKTS = 86 161 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_RXMTPKTS = 87 162 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_RXPKTS = 88 163 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_OOPKTS = 89 164 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_DROP_RST = 90 165 | ,NSTAT_SYSINFO_ECN_IFNET_TOTAL_CONN = 91 166 | // NSTAT_SYSINFO_ENUM_VERSION must be updated any time a value is added 167 | #define NSTAT_SYSINFO_ENUM_VERSION 20151208 168 | }; 169 | 170 | #pragma mark -- Network Statistics Providers -- 171 | 172 | 173 | // Interface properties 174 | 175 | #define NSTAT_IFNET_IS_UNKNOWN_TYPE 0x01 176 | #define NSTAT_IFNET_IS_LOOPBACK 0x02 177 | #define NSTAT_IFNET_IS_CELLULAR 0x04 178 | #define NSTAT_IFNET_IS_WIFI 0x08 179 | #define NSTAT_IFNET_IS_WIRED 0x10 180 | #define NSTAT_IFNET_IS_AWDL 0x20 181 | #define NSTAT_IFNET_IS_EXPENSIVE 0x40 182 | #define NSTAT_IFNET_IS_VPN 0x80 183 | #define NSTAT_IFNET_VIA_CELLFALLBACK 0x100 184 | 185 | enum 186 | { 187 | // generic response messages 188 | NSTAT_MSG_TYPE_SUCCESS = 0 189 | ,NSTAT_MSG_TYPE_ERROR = 1 190 | 191 | // Requests 192 | ,NSTAT_MSG_TYPE_ADD_SRC = 1001 193 | ,NSTAT_MSG_TYPE_ADD_ALL_SRCS = 1002 194 | ,NSTAT_MSG_TYPE_REM_SRC = 1003 195 | ,NSTAT_MSG_TYPE_QUERY_SRC = 1004 196 | ,NSTAT_MSG_TYPE_GET_SRC_DESC = 1005 197 | ,NSTAT_MSG_TYPE_SET_FILTER = 1006 198 | 199 | // Responses/Notfications 200 | ,NSTAT_MSG_TYPE_SRC_ADDED = 10001 201 | ,NSTAT_MSG_TYPE_SRC_REMOVED = 10002 202 | ,NSTAT_MSG_TYPE_SRC_DESC = 10003 203 | ,NSTAT_MSG_TYPE_SRC_COUNTS = 10004 204 | }; 205 | 206 | 207 | enum 208 | { 209 | NSTAT_PROVIDER_NONE = 0 210 | ,NSTAT_PROVIDER_ROUTE = 1 211 | ,NSTAT_PROVIDER_TCP = 2 212 | ,NSTAT_PROVIDER_UDP = 3 213 | ,NSTAT_PROVIDER_IFNET = 4 214 | ,NSTAT_PROVIDER_SYSINFO = 5 215 | }; 216 | #define NSTAT_PROVIDER_LAST NSTAT_PROVIDER_SYSINFO 217 | #define NSTAT_PROVIDER_COUNT (NSTAT_PROVIDER_LAST+1) 218 | 219 | typedef struct nstat_route_add_param 220 | { 221 | union 222 | { 223 | struct sockaddr_in v4; 224 | struct sockaddr_in6 v6; 225 | } dst; 226 | union 227 | { 228 | struct sockaddr_in v4; 229 | struct sockaddr_in6 v6; 230 | } mask; 231 | u_int32_t ifindex; 232 | } nstat_route_add_param; 233 | 234 | typedef struct nstat_tcp_add_param 235 | { 236 | union 237 | { 238 | struct sockaddr_in v4; 239 | struct sockaddr_in6 v6; 240 | } local; 241 | union 242 | { 243 | struct sockaddr_in v4; 244 | struct sockaddr_in6 v6; 245 | } remote; 246 | } nstat_tcp_add_param; 247 | 248 | typedef struct nstat_tcp_descriptor 249 | { 250 | union 251 | { 252 | struct sockaddr_in v4; 253 | struct sockaddr_in6 v6; 254 | } local; 255 | 256 | union 257 | { 258 | struct sockaddr_in v4; 259 | struct sockaddr_in6 v6; 260 | } remote; 261 | 262 | u_int32_t ifindex; 263 | 264 | u_int32_t state; 265 | 266 | u_int32_t sndbufsize; 267 | u_int32_t sndbufused; 268 | u_int32_t rcvbufsize; 269 | u_int32_t rcvbufused; 270 | u_int32_t txunacked; 271 | u_int32_t txwindow; 272 | u_int32_t txcwindow; 273 | u_int32_t traffic_class; 274 | u_int32_t traffic_mgt_flags; 275 | char cc_algo[16]; 276 | 277 | u_int64_t upid; 278 | u_int32_t pid; 279 | char pname[64]; 280 | u_int64_t eupid; 281 | u_int32_t epid; 282 | 283 | uint8_t uuid[16]; 284 | uint8_t euuid[16]; 285 | uint8_t vuuid[16]; 286 | struct tcp_conn_status connstatus; 287 | uint16_t ifnet_properties __attribute__((aligned(4))); 288 | } nstat_tcp_descriptor; 289 | 290 | typedef struct nstat_tcp_add_param nstat_udp_add_param; 291 | 292 | typedef struct nstat_udp_descriptor 293 | { 294 | union 295 | { 296 | struct sockaddr_in v4; 297 | struct sockaddr_in6 v6; 298 | } local; 299 | 300 | union 301 | { 302 | struct sockaddr_in v4; 303 | struct sockaddr_in6 v6; 304 | } remote; 305 | 306 | u_int32_t ifindex; 307 | 308 | u_int32_t rcvbufsize; 309 | u_int32_t rcvbufused; 310 | u_int32_t traffic_class; 311 | 312 | u_int64_t upid; 313 | u_int32_t pid; 314 | char pname[64]; 315 | u_int64_t eupid; 316 | u_int32_t epid; 317 | 318 | uint8_t uuid[16]; 319 | uint8_t euuid[16]; 320 | uint8_t vuuid[16]; 321 | uint16_t ifnet_properties; 322 | } nstat_udp_descriptor; 323 | 324 | typedef struct nstat_route_descriptor 325 | { 326 | u_int64_t id; 327 | u_int64_t parent_id; 328 | u_int64_t gateway_id; 329 | 330 | union 331 | { 332 | struct sockaddr_in v4; 333 | struct sockaddr_in6 v6; 334 | struct sockaddr sa; 335 | } dst; 336 | 337 | union 338 | { 339 | struct sockaddr_in v4; 340 | struct sockaddr_in6 v6; 341 | struct sockaddr sa; 342 | } mask; 343 | 344 | union 345 | { 346 | struct sockaddr_in v4; 347 | struct sockaddr_in6 v6; 348 | struct sockaddr sa; 349 | } gateway; 350 | 351 | u_int32_t ifindex; 352 | u_int32_t flags; 353 | 354 | } nstat_route_descriptor; 355 | 356 | typedef struct nstat_ifnet_add_param 357 | { 358 | u_int32_t ifindex; 359 | u_int64_t threshold; 360 | } nstat_ifnet_add_param; 361 | 362 | typedef struct nstat_ifnet_desc_cellular_status 363 | { 364 | u_int32_t valid_bitmask; /* indicates which fields are valid */ 365 | #define NSTAT_IFNET_DESC_CELL_LINK_QUALITY_METRIC_VALID 0x1 366 | #define NSTAT_IFNET_DESC_CELL_UL_EFFECTIVE_BANDWIDTH_VALID 0x2 367 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_BANDWIDTH_VALID 0x4 368 | #define NSTAT_IFNET_DESC_CELL_UL_MIN_LATENCY_VALID 0x8 369 | #define NSTAT_IFNET_DESC_CELL_UL_EFFECTIVE_LATENCY_VALID 0x10 370 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_LATENCY_VALID 0x20 371 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_VALID 0x40 372 | #define NSTAT_IFNET_DESC_CELL_UL_BYTES_LOST_VALID 0x80 373 | #define NSTAT_IFNET_DESC_CELL_UL_MIN_QUEUE_SIZE_VALID 0x100 374 | #define NSTAT_IFNET_DESC_CELL_UL_AVG_QUEUE_SIZE_VALID 0x200 375 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_QUEUE_SIZE_VALID 0x400 376 | #define NSTAT_IFNET_DESC_CELL_DL_EFFECTIVE_BANDWIDTH_VALID 0x800 377 | #define NSTAT_IFNET_DESC_CELL_DL_MAX_BANDWIDTH_VALID 0x1000 378 | #define NSTAT_IFNET_DESC_CELL_CONFIG_INACTIVITY_TIME_VALID 0x2000 379 | #define NSTAT_IFNET_DESC_CELL_CONFIG_BACKOFF_TIME_VALID 0x4000 380 | u_int32_t link_quality_metric; 381 | u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on 382 | current activity (bps) */ 383 | u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth 384 | (bps) */ 385 | u_int32_t ul_min_latency; /* min expected uplink latency for first hop 386 | (ms) */ 387 | u_int32_t ul_effective_latency; /* current expected uplink latency for 388 | first hop (ms) */ 389 | u_int32_t ul_max_latency; /* max expected uplink latency first hop 390 | (ms) */ 391 | u_int32_t ul_retxt_level; /* Retransmission metric */ 392 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_NONE 1 393 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_LOW 2 394 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_MEDIUM 3 395 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_HIGH 4 396 | 397 | u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 398 | format */ 399 | u_int32_t ul_min_queue_size; /* minimum bytes in queue */ 400 | u_int32_t ul_avg_queue_size; /* average bytes in queue */ 401 | u_int32_t ul_max_queue_size; /* maximum bytes in queue */ 402 | u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based 403 | on current activity (bps) */ 404 | u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth 405 | (bps) */ 406 | u_int32_t config_inactivity_time; /* ms */ 407 | u_int32_t config_backoff_time; /* new connections backoff time in ms */ 408 | } nstat_ifnet_desc_cellular_status; 409 | 410 | typedef struct nstat_ifnet_desc_wifi_status { 411 | u_int32_t valid_bitmask; 412 | #define NSTAT_IFNET_DESC_WIFI_LINK_QUALITY_METRIC_VALID 0x1 413 | #define NSTAT_IFNET_DESC_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID 0x2 414 | #define NSTAT_IFNET_DESC_WIFI_UL_MAX_BANDWIDTH_VALID 0x4 415 | #define NSTAT_IFNET_DESC_WIFI_UL_MIN_LATENCY_VALID 0x8 416 | #define NSTAT_IFNET_DESC_WIFI_UL_EFFECTIVE_LATENCY_VALID 0x10 417 | #define NSTAT_IFNET_DESC_WIFI_UL_MAX_LATENCY_VALID 0x20 418 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_VALID 0x40 419 | #define NSTAT_IFNET_DESC_WIFI_UL_ERROR_RATE_VALID 0x80 420 | #define NSTAT_IFNET_DESC_WIFI_UL_BYTES_LOST_VALID 0x100 421 | #define NSTAT_IFNET_DESC_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID 0x200 422 | #define NSTAT_IFNET_DESC_WIFI_DL_MAX_BANDWIDTH_VALID 0x400 423 | #define NSTAT_IFNET_DESC_WIFI_DL_MIN_LATENCY_VALID 0x800 424 | #define NSTAT_IFNET_DESC_WIFI_DL_EFFECTIVE_LATENCY_VALID 0x1000 425 | #define NSTAT_IFNET_DESC_WIFI_DL_MAX_LATENCY_VALID 0x2000 426 | #define NSTAT_IFNET_DESC_WIFI_DL_ERROR_RATE_VALID 0x4000 427 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_VALID 0x8000 428 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_MULTICAST_RATE_VALID 0x10000 429 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_SCAN_COUNT_VALID 0x20000 430 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_SCAN_DURATION_VALID 0x40000 431 | u_int32_t link_quality_metric; /* link quality metric */ 432 | u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on 433 | current activity (bps) */ 434 | u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth 435 | (bps) */ 436 | u_int32_t ul_min_latency; /* min expected uplink latency for first hop 437 | (ms) */ 438 | u_int32_t ul_effective_latency; /* current expected uplink latency for 439 | first hop (ms) */ 440 | u_int32_t ul_max_latency; /* max expected uplink latency for first hop 441 | (ms) */ 442 | u_int32_t ul_retxt_level; /* Retransmission metric */ 443 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_NONE 1 444 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_LOW 2 445 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_MEDIUM 3 446 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_HIGH 4 447 | 448 | u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 449 | format */ 450 | u_int32_t ul_error_rate; /* % of bytes dropped on uplink after many 451 | retransmissions in Q10 format */ 452 | u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based 453 | on current activity (bps) */ 454 | u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth 455 | (bps) */ 456 | /* 457 | * The download latency values indicate the time AP may have to wait 458 | * for the driver to receive the packet. These values give the range 459 | * of expected latency mainly due to co-existence events and channel 460 | * hopping where the interface becomes unavailable. 461 | */ 462 | u_int32_t dl_min_latency; /* min expected latency for first hop in ms */ 463 | u_int32_t dl_effective_latency; /* current expected latency for first 464 | hop in ms */ 465 | u_int32_t dl_max_latency; /* max expected latency for first hop in ms */ 466 | u_int32_t dl_error_rate; /* % of CRC or other errors in Q10 format */ 467 | u_int32_t config_frequency; /* 2.4 or 5 GHz */ 468 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_2_4_GHZ 1 469 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_5_0_GHZ 2 470 | u_int32_t config_multicast_rate; /* bps */ 471 | u_int32_t scan_count; /* scan count during the previous period */ 472 | u_int32_t scan_duration; /* scan duration in ms */ 473 | } nstat_ifnet_desc_wifi_status; 474 | 475 | enum 476 | { 477 | NSTAT_IFNET_DESC_LINK_STATUS_TYPE_NONE = 0 478 | ,NSTAT_IFNET_DESC_LINK_STATUS_TYPE_CELLULAR = 1 479 | ,NSTAT_IFNET_DESC_LINK_STATUS_TYPE_WIFI = 2 480 | }; 481 | 482 | typedef struct nstat_ifnet_desc_link_status 483 | { 484 | u_int32_t link_status_type; 485 | union { 486 | nstat_ifnet_desc_cellular_status cellular; 487 | nstat_ifnet_desc_wifi_status wifi; 488 | } u; 489 | } nstat_ifnet_desc_link_status; 490 | 491 | #ifndef IF_DESCSIZE 492 | #define IF_DESCSIZE 128 493 | #endif 494 | typedef struct nstat_ifnet_descriptor 495 | { 496 | char name[IFNAMSIZ+1]; 497 | u_int32_t ifindex; 498 | u_int64_t threshold; 499 | unsigned int type; 500 | char description[IF_DESCSIZE]; 501 | nstat_ifnet_desc_link_status link_status; 502 | } nstat_ifnet_descriptor; 503 | 504 | typedef struct nstat_sysinfo_descriptor 505 | { 506 | u_int32_t flags; 507 | } nstat_sysinfo_descriptor; 508 | 509 | typedef struct nstat_sysinfo_add_param 510 | { 511 | /* To indicate which system level information should be collected */ 512 | u_int32_t flags; 513 | } nstat_sysinfo_add_param; 514 | 515 | #define NSTAT_SYSINFO_MBUF_STATS 0x0001 516 | #define NSTAT_SYSINFO_TCP_STATS 0x0002 517 | #define NSTAT_SYSINFO_IFNET_ECN_STATS 0x0003 518 | 519 | #pragma mark -- Network Statistics User Client -- 520 | 521 | #define NET_STAT_CONTROL_NAME "com.apple.network.statistics" 522 | 523 | 524 | enum 525 | { 526 | NSTAT_SRC_REF_ALL = 0xffffffff 527 | ,NSTAT_SRC_REF_INVALID = 0 528 | }; 529 | 530 | /* Source-level filters */ 531 | enum 532 | { 533 | NSTAT_FILTER_NOZEROBYTES = 0x00000001 534 | }; 535 | 536 | /* Provider-level filters */ 537 | enum 538 | { 539 | NSTAT_FILTER_ACCEPT_UNKNOWN = 0x00000001 540 | ,NSTAT_FILTER_ACCEPT_LOOPBACK = 0x00000002 541 | ,NSTAT_FILTER_ACCEPT_CELLULAR = 0x00000004 542 | ,NSTAT_FILTER_ACCEPT_WIFI = 0x00000008 543 | ,NSTAT_FILTER_ACCEPT_WIRED = 0x00000010 544 | ,NSTAT_FILTER_ACCEPT_ALL = 0x0000001F 545 | ,NSTAT_FILTER_IFNET_FLAGS = 0x000000FF 546 | 547 | ,NSTAT_FILTER_PROVIDER_NOZEROBYTES = 0x00000100 548 | 549 | ,NSTAT_FILTER_TCP_NO_LISTENER = 0x00001000 550 | ,NSTAT_FILTER_TCP_ONLY_LISTENER = 0x00002000 551 | ,NSTAT_FILTER_TCP_INTERFACE_ATTACH = 0x00004000 552 | ,NSTAT_FILTER_TCP_FLAGS = 0x0000F000 553 | 554 | ,NSTAT_FILTER_UDP_INTERFACE_ATTACH = 0x00010000 555 | ,NSTAT_FILTER_UDP_FLAGS = 0x000F0000 556 | 557 | ,NSTAT_FILTER_SUPPRESS_SRC_ADDED = 0x00100000 558 | ,NSTAT_FILTER_REQUIRE_SRC_ADDED = 0x00200000 559 | }; 560 | 561 | enum 562 | { 563 | NSTAT_MSG_HDR_FLAG_SUPPORTS_AGGREGATE = 1 << 0, 564 | NSTAT_MSG_HDR_FLAG_CONTINUATION = 1 << 1, 565 | NSTAT_MSG_HDR_FLAG_CLOSING = 1 << 2, 566 | }; 567 | /* 568 | typedef struct nstat_msg_hdr 569 | { 570 | u_int64_t context; 571 | u_int32_t type; 572 | u_int16_t length; 573 | u_int16_t flags; 574 | } nstat_msg_hdr; 575 | */ 576 | 577 | typedef struct nstat_msg_error 578 | { 579 | nstat_msg_hdr hdr; 580 | u_int32_t error; // errno error 581 | } nstat_msg_error; 582 | 583 | typedef struct nstat_msg_add_src 584 | { 585 | nstat_msg_hdr hdr; 586 | nstat_provider_id_t provider; 587 | u_int8_t param[]; 588 | } nstat_msg_add_src_req; 589 | 590 | typedef struct nstat_msg_add_all_srcs 591 | { 592 | nstat_msg_hdr hdr; 593 | nstat_provider_id_t provider; 594 | u_int64_t filter; 595 | } nstat_msg_add_all_srcs; 596 | 597 | typedef struct nstat_msg_src_added 598 | { 599 | nstat_msg_hdr hdr; 600 | nstat_provider_id_t provider; 601 | nstat_src_ref_t srcref; 602 | } nstat_msg_src_added; 603 | 604 | typedef struct nstat_msg_rem_src 605 | { 606 | nstat_msg_hdr hdr; 607 | nstat_src_ref_t srcref; 608 | } nstat_msg_rem_src_req; 609 | 610 | typedef struct nstat_msg_get_src_description 611 | { 612 | nstat_msg_hdr hdr; 613 | nstat_src_ref_t srcref; 614 | } nstat_msg_get_src_description; 615 | 616 | typedef struct nstat_msg_set_filter 617 | { 618 | nstat_msg_hdr hdr; 619 | nstat_src_ref_t srcref; 620 | u_int32_t filter; 621 | } nstat_msg_set_filter; 622 | 623 | typedef struct nstat_msg_src_description 624 | { 625 | nstat_msg_hdr hdr; 626 | nstat_src_ref_t srcref; 627 | nstat_provider_id_t provider; 628 | u_int8_t data[]; 629 | } nstat_msg_src_description; 630 | 631 | typedef struct nstat_msg_query_src 632 | { 633 | nstat_msg_hdr hdr; 634 | nstat_src_ref_t srcref; 635 | } nstat_msg_query_src_req; 636 | 637 | typedef struct nstat_msg_src_counts 638 | { 639 | nstat_msg_hdr hdr; 640 | nstat_src_ref_t srcref; 641 | nstat_counts counts; 642 | } nstat_msg_src_counts; 643 | 644 | typedef struct nstat_msg_src_update 645 | { 646 | nstat_msg_hdr hdr; 647 | nstat_src_ref_t srcref; 648 | nstat_counts counts; 649 | nstat_provider_id_t provider; 650 | u_int8_t data[]; 651 | } nstat_msg_src_update; 652 | 653 | typedef struct nstat_msg_src_removed 654 | { 655 | nstat_msg_hdr hdr; 656 | nstat_src_ref_t srcref; 657 | } nstat_msg_src_removed; 658 | 659 | typedef struct nstat_msg_sysinfo_counts 660 | { 661 | nstat_msg_hdr hdr; 662 | nstat_src_ref_t srcref; 663 | nstat_sysinfo_counts counts; 664 | } __attribute__((packed)) nstat_msg_sysinfo_counts; 665 | 666 | #pragma pack(pop) 667 | -------------------------------------------------------------------------------- /src/ntstat_kernel_3789.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "NTStatKernelStructHandler.hpp" 3 | 4 | // definitions from darwin-xnu/bsd/net/ntstat.h kernel header 5 | 6 | #include 7 | 8 | #include "ntstat_kernel_3789.h" 9 | 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class NTStatKernel3789 : public NTStatKernelStructHandler 16 | { 17 | public: 18 | 19 | virtual bool isProviderTcp(uint64_t providerId){ 20 | return (NSTAT_PROVIDER_TCP_KERNEL == providerId)||(NSTAT_PROVIDER_TCP_USERLAND);} 21 | 22 | virtual bool isProviderUdp(uint64_t providerId) { 23 | return (NSTAT_PROVIDER_UDP_KERNEL == providerId)||(NSTAT_PROVIDER_UDP_USERLAND);} 24 | 25 | virtual bool isProviderInterface(uint64_t providerId) { return NSTAT_PROVIDER_IFNET == providerId; } 26 | 27 | //-------------------------------------------------------------------- 28 | // write GET_SRC_DESC message to dest 29 | //-------------------------------------------------------------------- 30 | virtual void writeSrcDesc(MsgDest &dest, uint64_t providerId, uint64_t srcRef ) 31 | { 32 | nstat_msg_get_src_description msg = nstat_msg_get_src_description(); 33 | 34 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_GET_SRC_DESC); 35 | 36 | msg.srcref = srcRef; 37 | 38 | dest.send(&msg.hdr, sizeof(msg)); 39 | } 40 | 41 | //-------------------------------------------------------------------- 42 | // write QUERY_SRC message to dest 43 | //-------------------------------------------------------------------- 44 | virtual void writeQuerySrc(MsgDest &dest, uint64_t srcRef) 45 | { 46 | nstat_msg_query_src_req msg = nstat_msg_query_src_req(); 47 | 48 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_QUERY_SRC); 49 | 50 | msg.srcref= srcRef; 51 | 52 | dest.send(&msg.hdr, sizeof(msg)); 53 | } 54 | 55 | //-------------------------------------------------------------------- 56 | // write ADD_ADD_SRCS message to dest 57 | //-------------------------------------------------------------------- 58 | virtual void writeAddAllSrc(MsgDest &dest, uint32_t providerId) 59 | { 60 | nstat_msg_add_all_srcs msg = nstat_msg_add_all_srcs(); 61 | 62 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_ADD_ALL_SRCS); 63 | 64 | msg.provider = providerId ; 65 | 66 | dest.send(&msg.hdr, sizeof(msg)); 67 | } 68 | 69 | // xnu-3789 is first time we see split _KERNEL and _USERLAND 70 | 71 | virtual void writeAddAllTcpSrc(MsgDest &dest) { 72 | writeAddAllSrc(dest, NSTAT_PROVIDER_TCP_KERNEL); 73 | // writeAddAllSrc(dest, NSTAT_PROVIDER_TCP_USERLAND); // this just sends repeat of all KERNEL srcs 74 | } 75 | 76 | virtual void writeAddAllUdpSrc(MsgDest &dest) { 77 | writeAddAllSrc(dest, NSTAT_PROVIDER_UDP_KERNEL); 78 | //writeAddAllSrc(dest, NSTAT_PROVIDER_UDP_USERLAND); 79 | } 80 | 81 | //-------------------------------------------------------------------- 82 | // extract srcRef, providerId (if possible) from message 83 | //-------------------------------------------------------------------- 84 | virtual void getSrcRef(nstat_msg_hdr* msg, int structlen, uint64_t &srcRef, uint32_t &providerId) { 85 | switch(msg->type) 86 | { 87 | case NSTAT_MSG_TYPE_SRC_COUNTS: 88 | srcRef = ((nstat_msg_src_counts*)msg)->srcref; 89 | break; 90 | case NSTAT_MSG_TYPE_SRC_DESC: 91 | srcRef = ((nstat_msg_src_description*)msg)->srcref; 92 | providerId = ((nstat_msg_src_description*)msg)->provider; 93 | break; 94 | case NSTAT_MSG_TYPE_SRC_ADDED: 95 | srcRef = ((nstat_msg_src_added*)msg)->srcref; 96 | providerId = ((nstat_msg_src_added*)msg)->provider; 97 | break; 98 | case NSTAT_MSG_TYPE_SRC_REMOVED: 99 | srcRef = ((nstat_msg_src_removed*)msg)->srcref; 100 | break; 101 | case NSTAT_MSG_TYPE_QUERY_SRC: 102 | srcRef = ((nstat_msg_query_src*)msg)->srcref; 103 | break; 104 | case NSTAT_MSG_TYPE_GET_SRC_DESC: 105 | srcRef = ((nstat_msg_get_src_description*)msg)->srcref; 106 | break; 107 | case NSTAT_MSG_TYPE_REM_SRC: 108 | srcRef = ((nstat_msg_rem_src*)msg)->srcref; 109 | break; 110 | default: 111 | //printf("E getSrcRef not implemented for type %d\n", msg->type); 112 | break; 113 | } 114 | } 115 | 116 | //-------------------------------------------------------------------- 117 | // populate dest with message data 118 | //-------------------------------------------------------------------- 119 | virtual bool readSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 120 | { 121 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 122 | if (msg->provider == NSTAT_PROVIDER_TCP_KERNEL || msg->provider == NSTAT_PROVIDER_TCP_USERLAND) { 123 | readTcpSrcDesc(hdr, structlen, dest); 124 | } else if (msg->provider == NSTAT_PROVIDER_UDP_KERNEL || msg->provider == NSTAT_PROVIDER_UDP_USERLAND) { 125 | readUdpSrcDesc(hdr, structlen, dest); 126 | } else { 127 | // ?? 128 | return false; 129 | } 130 | return true; 131 | } 132 | 133 | //-------------------------------------------------------------------- 134 | // populate dest with message ifnet data 135 | //-------------------------------------------------------------------- 136 | /* 137 | virtual bool readSrcDesc(nstat_msg_hdr* hdr, int structlen, NTStatInterface* dest ) 138 | { 139 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 140 | if (msg->provider != NSTAT_PROVIDER_IFNET) return false; 141 | 142 | nstat_ifnet_descriptor* ifnet = (nstat_ifnet_descriptor*)msg->data; 143 | dest->name = string(ifnet->name); 144 | dest->description = string(ifnet->description); 145 | dest->ifindex = ifnet->ifindex; 146 | dest->type = ifnet->type; 147 | 148 | return false; 149 | } 150 | */ 151 | 152 | 153 | //-------------------------------------------------------------------- 154 | // TCP: populate dest with message data 155 | //-------------------------------------------------------------------- 156 | virtual void readTcpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 157 | { 158 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 159 | nstat_tcp_descriptor*tcp = (nstat_tcp_descriptor*)msg->data; 160 | 161 | dest->key.ifindex = tcp->ifindex; 162 | dest->key.ipproto = IPPROTO_TCP; 163 | dest->key.isV6 = (tcp->local.v4.sin_family == AF_INET6); 164 | 165 | if (tcp->local.v4.sin_family == AF_INET6) 166 | { 167 | dest->key.lport = tcp->local.v6.sin6_port; 168 | dest->key.local.addr6 = tcp->local.v6.sin6_addr; 169 | dest->key.rport = tcp->remote.v6.sin6_port; 170 | dest->key.remote.addr6 = tcp->remote.v6.sin6_addr; 171 | } else { 172 | dest->key.lport = tcp->local.v4.sin_port; 173 | dest->key.rport = tcp->remote.v4.sin_port; 174 | dest->key.local.addr4 = tcp->local.v4.sin_addr; 175 | dest->key.remote.addr4 = tcp->remote.v4.sin_addr; 176 | } 177 | dest->states.txwindow = tcp->txwindow; 178 | dest->states.txcwindow = tcp->txcwindow; 179 | dest->states.state = tcp->state; 180 | 181 | dest->process.pid = tcp->pid; 182 | 183 | strcpy(dest->process.name, ((tcp->pid > 0 && tcp->pname[0]) ? tcp->pname : "")); 184 | } 185 | 186 | //-------------------------------------------------------------------- 187 | // UDP: populate dest with message data 188 | //-------------------------------------------------------------------- 189 | virtual void readUdpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 190 | { 191 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 192 | nstat_udp_descriptor*udp = (nstat_udp_descriptor*)msg->data; 193 | 194 | dest->key.ifindex = udp->ifindex; 195 | dest->key.ipproto = IPPROTO_UDP; 196 | dest->key.isV6 = (udp->local.v4.sin_family == AF_INET6); 197 | 198 | if (udp->local.v4.sin_family == AF_INET6) 199 | { 200 | dest->key.lport = udp->local.v6.sin6_port; 201 | dest->key.rport = udp->remote.v6.sin6_port; 202 | dest->key.local.addr6 = udp->local.v6.sin6_addr; 203 | dest->key.remote.addr6 = udp->remote.v6.sin6_addr; 204 | } else { 205 | dest->key.lport = udp->local.v4.sin_port; 206 | dest->key.rport = udp->remote.v4.sin_port; 207 | dest->key.local.addr4 = udp->local.v4.sin_addr; 208 | dest->key.remote.addr4 = udp->remote.v4.sin_addr; 209 | } 210 | 211 | dest->process.pid = udp->pid; 212 | strcpy(dest->process.name, ((udp->pid > 0 && udp->pname[0]) ? udp->pname : "")); 213 | } 214 | 215 | //-------------------------------------------------------------------- 216 | // populate dest with message counts data 217 | //-------------------------------------------------------------------- 218 | virtual void readCounts(nstat_msg_hdr*hdr, int structlen, NTStatCounters& dest ) 219 | { 220 | nstat_msg_src_counts *msg = (nstat_msg_src_counts*)hdr; 221 | dest.rxbytes = msg->counts.nstat_rxbytes; 222 | dest.txbytes = msg->counts.nstat_txbytes; 223 | dest.rxpackets = msg->counts.nstat_rxpackets; 224 | dest.txpackets = msg->counts.nstat_txpackets; 225 | 226 | dest.cell_rxbytes = msg->counts.nstat_cell_rxbytes; 227 | dest.cell_txbytes = msg->counts.nstat_cell_txbytes; 228 | 229 | dest.wifi_rxbytes = msg->counts.nstat_wifi_rxbytes; 230 | dest.wifi_txbytes = msg->counts.nstat_wifi_txbytes; 231 | 232 | dest.wired_rxbytes = msg->counts.nstat_wired_rxbytes; 233 | dest.wired_txbytes = msg->counts.nstat_wired_txbytes; 234 | } 235 | 236 | }; 237 | 238 | 239 | NTStatKernelStructHandler* NewNTStatKernel3789() { 240 | return new NTStatKernel3789(); 241 | } 242 | -------------------------------------------------------------------------------- /src/ntstat_kernel_3789.h: -------------------------------------------------------------------------------- 1 | // https://github.com/apple/darwin-xnu 2 | // git checkout xnu-3789.70.16 3 | // Sierra 10.12 4 | 5 | 6 | // bsd/netinet/tcp.h 7 | struct tcp_conn_status { 8 | unsigned int probe_activated : 1; 9 | unsigned int write_probe_failed : 1; 10 | unsigned int read_probe_failed : 1; 11 | unsigned int conn_probe_failed : 1; 12 | }; 13 | #define IFNAMSIZ 16 14 | 15 | 16 | // bsd/net/ntstat.h 17 | 18 | enum 19 | { 20 | NSTAT_PROVIDER_NONE = 0 21 | ,NSTAT_PROVIDER_ROUTE = 1 22 | ,NSTAT_PROVIDER_TCP_KERNEL = 2 23 | ,NSTAT_PROVIDER_TCP_USERLAND = 3 24 | ,NSTAT_PROVIDER_UDP_KERNEL = 4 25 | ,NSTAT_PROVIDER_UDP_USERLAND = 5 26 | ,NSTAT_PROVIDER_IFNET = 6 27 | ,NSTAT_PROVIDER_SYSINFO = 7 28 | }; 29 | 30 | enum 31 | { 32 | // generic response messages 33 | NSTAT_MSG_TYPE_SUCCESS = 0 34 | ,NSTAT_MSG_TYPE_ERROR = 1 35 | 36 | // Requests 37 | ,NSTAT_MSG_TYPE_ADD_SRC = 1001 38 | ,NSTAT_MSG_TYPE_ADD_ALL_SRCS = 1002 39 | ,NSTAT_MSG_TYPE_REM_SRC = 1003 40 | ,NSTAT_MSG_TYPE_QUERY_SRC = 1004 41 | ,NSTAT_MSG_TYPE_GET_SRC_DESC = 1005 42 | 43 | // Responses/Notfications 44 | ,NSTAT_MSG_TYPE_SRC_ADDED = 10001 45 | ,NSTAT_MSG_TYPE_SRC_REMOVED = 10002 46 | ,NSTAT_MSG_TYPE_SRC_DESC = 10003 47 | ,NSTAT_MSG_TYPE_SRC_COUNTS = 10004 48 | }; 49 | 50 | enum 51 | { 52 | NSTAT_SRC_REF_ALL = 0xffffffffffffffffULL 53 | ,NSTAT_SRC_REF_INVALID = 0 54 | }; 55 | 56 | 57 | #pragma pack(push, 4) 58 | #define __NSTAT_REVISION__ 8 59 | 60 | typedef u_int32_t nstat_provider_id_t; 61 | typedef u_int64_t nstat_src_ref_t; 62 | typedef u_int64_t nstat_event_flags_t; 63 | 64 | /* 65 | typedef struct nstat_msg_hdr 66 | { 67 | u_int64_t context; 68 | u_int32_t type; 69 | u_int16_t length; 70 | u_int16_t flags; 71 | } nstat_msg_hdr; 72 | */ 73 | 74 | typedef struct nstat_counts 75 | { 76 | /* Counters */ 77 | u_int64_t nstat_rxpackets __attribute__((aligned(8))); 78 | u_int64_t nstat_rxbytes __attribute__((aligned(8))); 79 | u_int64_t nstat_txpackets __attribute__((aligned(8))); 80 | u_int64_t nstat_txbytes __attribute__((aligned(8))); 81 | 82 | u_int32_t nstat_rxduplicatebytes; 83 | u_int32_t nstat_rxoutoforderbytes; 84 | u_int32_t nstat_txretransmit; 85 | 86 | u_int32_t nstat_connectattempts; 87 | u_int32_t nstat_connectsuccesses; 88 | 89 | u_int32_t nstat_min_rtt; 90 | u_int32_t nstat_avg_rtt; 91 | u_int32_t nstat_var_rtt; 92 | 93 | u_int64_t nstat_cell_rxbytes __attribute__((aligned(8))); 94 | u_int64_t nstat_cell_txbytes __attribute__((aligned(8))); 95 | u_int64_t nstat_wifi_rxbytes __attribute__((aligned(8))); 96 | u_int64_t nstat_wifi_txbytes __attribute__((aligned(8))); 97 | u_int64_t nstat_wired_rxbytes __attribute__((aligned(8))); 98 | u_int64_t nstat_wired_txbytes __attribute__((aligned(8))); 99 | } nstat_counts; 100 | 101 | typedef struct nstat_tcp_descriptor 102 | { 103 | union 104 | { 105 | struct sockaddr_in v4; 106 | struct sockaddr_in6 v6; 107 | } local; 108 | 109 | union 110 | { 111 | struct sockaddr_in v4; 112 | struct sockaddr_in6 v6; 113 | } remote; 114 | 115 | u_int32_t ifindex; 116 | 117 | u_int32_t state; 118 | 119 | u_int32_t sndbufsize; 120 | u_int32_t sndbufused; 121 | u_int32_t rcvbufsize; 122 | u_int32_t rcvbufused; 123 | u_int32_t txunacked; 124 | u_int32_t txwindow; 125 | u_int32_t txcwindow; 126 | u_int32_t traffic_class; 127 | u_int32_t traffic_mgt_flags; 128 | char cc_algo[16]; 129 | 130 | u_int64_t upid; 131 | u_int32_t pid; 132 | char pname[64]; 133 | u_int64_t eupid; 134 | u_int32_t epid; 135 | 136 | uuid_t uuid; 137 | uuid_t euuid; 138 | uuid_t vuuid; 139 | struct tcp_conn_status connstatus; 140 | uint16_t ifnet_properties __attribute__((aligned(4))); 141 | } nstat_tcp_descriptor; 142 | 143 | typedef struct nstat_udp_descriptor 144 | { 145 | union 146 | { 147 | struct sockaddr_in v4; 148 | struct sockaddr_in6 v6; 149 | } local; 150 | 151 | union 152 | { 153 | struct sockaddr_in v4; 154 | struct sockaddr_in6 v6; 155 | } remote; 156 | 157 | u_int32_t ifindex; 158 | 159 | u_int32_t rcvbufsize; 160 | u_int32_t rcvbufused; 161 | u_int32_t traffic_class; 162 | 163 | u_int64_t upid; 164 | u_int32_t pid; 165 | char pname[64]; 166 | u_int64_t eupid; 167 | u_int32_t epid; 168 | 169 | uuid_t uuid; 170 | uuid_t euuid; 171 | uuid_t vuuid; 172 | uint16_t ifnet_properties; 173 | } nstat_udp_descriptor; 174 | 175 | typedef struct nstat_ifnet_desc_cellular_status 176 | { 177 | u_int32_t valid_bitmask; /* indicates which fields are valid */ 178 | #define NSTAT_IFNET_DESC_CELL_LINK_QUALITY_METRIC_VALID 0x1 179 | #define NSTAT_IFNET_DESC_CELL_UL_EFFECTIVE_BANDWIDTH_VALID 0x2 180 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_BANDWIDTH_VALID 0x4 181 | #define NSTAT_IFNET_DESC_CELL_UL_MIN_LATENCY_VALID 0x8 182 | #define NSTAT_IFNET_DESC_CELL_UL_EFFECTIVE_LATENCY_VALID 0x10 183 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_LATENCY_VALID 0x20 184 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_VALID 0x40 185 | #define NSTAT_IFNET_DESC_CELL_UL_BYTES_LOST_VALID 0x80 186 | #define NSTAT_IFNET_DESC_CELL_UL_MIN_QUEUE_SIZE_VALID 0x100 187 | #define NSTAT_IFNET_DESC_CELL_UL_AVG_QUEUE_SIZE_VALID 0x200 188 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_QUEUE_SIZE_VALID 0x400 189 | #define NSTAT_IFNET_DESC_CELL_DL_EFFECTIVE_BANDWIDTH_VALID 0x800 190 | #define NSTAT_IFNET_DESC_CELL_DL_MAX_BANDWIDTH_VALID 0x1000 191 | #define NSTAT_IFNET_DESC_CELL_CONFIG_INACTIVITY_TIME_VALID 0x2000 192 | #define NSTAT_IFNET_DESC_CELL_CONFIG_BACKOFF_TIME_VALID 0x4000 193 | #define NSTAT_IFNET_DESC_CELL_MSS_RECOMMENDED_VALID 0x8000 194 | u_int32_t link_quality_metric; 195 | u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on 196 | current activity (bps) */ 197 | u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth 198 | (bps) */ 199 | u_int32_t ul_min_latency; /* min expected uplink latency for first hop 200 | (ms) */ 201 | u_int32_t ul_effective_latency; /* current expected uplink latency for 202 | first hop (ms) */ 203 | u_int32_t ul_max_latency; /* max expected uplink latency first hop 204 | (ms) */ 205 | u_int32_t ul_retxt_level; /* Retransmission metric */ 206 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_NONE 1 207 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_LOW 2 208 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_MEDIUM 3 209 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_HIGH 4 210 | 211 | u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 212 | format */ 213 | u_int32_t ul_min_queue_size; /* minimum bytes in queue */ 214 | u_int32_t ul_avg_queue_size; /* average bytes in queue */ 215 | u_int32_t ul_max_queue_size; /* maximum bytes in queue */ 216 | u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based 217 | on current activity (bps) */ 218 | u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth 219 | (bps) */ 220 | u_int32_t config_inactivity_time; /* ms */ 221 | u_int32_t config_backoff_time; /* new connections backoff time in ms */ 222 | #define NSTAT_IFNET_DESC_MSS_RECOMMENDED_NONE 0x0 223 | #define NSTAT_IFNET_DESC_MSS_RECOMMENDED_MEDIUM 0x1 224 | #define NSTAT_IFNET_DESC_MSS_RECOMMENDED_LOW 0x2 225 | u_int16_t mss_recommended; /* recommended MSS */ 226 | } nstat_ifnet_desc_cellular_status; 227 | 228 | typedef struct nstat_ifnet_desc_wifi_status { 229 | u_int32_t valid_bitmask; 230 | #define NSTAT_IFNET_DESC_WIFI_LINK_QUALITY_METRIC_VALID 0x1 231 | #define NSTAT_IFNET_DESC_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID 0x2 232 | #define NSTAT_IFNET_DESC_WIFI_UL_MAX_BANDWIDTH_VALID 0x4 233 | #define NSTAT_IFNET_DESC_WIFI_UL_MIN_LATENCY_VALID 0x8 234 | #define NSTAT_IFNET_DESC_WIFI_UL_EFFECTIVE_LATENCY_VALID 0x10 235 | #define NSTAT_IFNET_DESC_WIFI_UL_MAX_LATENCY_VALID 0x20 236 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_VALID 0x40 237 | #define NSTAT_IFNET_DESC_WIFI_UL_ERROR_RATE_VALID 0x80 238 | #define NSTAT_IFNET_DESC_WIFI_UL_BYTES_LOST_VALID 0x100 239 | #define NSTAT_IFNET_DESC_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID 0x200 240 | #define NSTAT_IFNET_DESC_WIFI_DL_MAX_BANDWIDTH_VALID 0x400 241 | #define NSTAT_IFNET_DESC_WIFI_DL_MIN_LATENCY_VALID 0x800 242 | #define NSTAT_IFNET_DESC_WIFI_DL_EFFECTIVE_LATENCY_VALID 0x1000 243 | #define NSTAT_IFNET_DESC_WIFI_DL_MAX_LATENCY_VALID 0x2000 244 | #define NSTAT_IFNET_DESC_WIFI_DL_ERROR_RATE_VALID 0x4000 245 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_VALID 0x8000 246 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_MULTICAST_RATE_VALID 0x10000 247 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_SCAN_COUNT_VALID 0x20000 248 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_SCAN_DURATION_VALID 0x40000 249 | u_int32_t link_quality_metric; /* link quality metric */ 250 | u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on 251 | current activity (bps) */ 252 | u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth 253 | (bps) */ 254 | u_int32_t ul_min_latency; /* min expected uplink latency for first hop 255 | (ms) */ 256 | u_int32_t ul_effective_latency; /* current expected uplink latency for 257 | first hop (ms) */ 258 | u_int32_t ul_max_latency; /* max expected uplink latency for first hop 259 | (ms) */ 260 | u_int32_t ul_retxt_level; /* Retransmission metric */ 261 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_NONE 1 262 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_LOW 2 263 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_MEDIUM 3 264 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_HIGH 4 265 | 266 | u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 267 | format */ 268 | u_int32_t ul_error_rate; /* % of bytes dropped on uplink after many 269 | retransmissions in Q10 format */ 270 | u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based 271 | on current activity (bps) */ 272 | u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth 273 | (bps) */ 274 | /* 275 | * The download latency values indicate the time AP may have to wait 276 | * for the driver to receive the packet. These values give the range 277 | * of expected latency mainly due to co-existence events and channel 278 | * hopping where the interface becomes unavailable. 279 | */ 280 | u_int32_t dl_min_latency; /* min expected latency for first hop in ms */ 281 | u_int32_t dl_effective_latency; /* current expected latency for first 282 | hop in ms */ 283 | u_int32_t dl_max_latency; /* max expected latency for first hop in ms */ 284 | u_int32_t dl_error_rate; /* % of CRC or other errors in Q10 format */ 285 | u_int32_t config_frequency; /* 2.4 or 5 GHz */ 286 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_2_4_GHZ 1 287 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_5_0_GHZ 2 288 | u_int32_t config_multicast_rate; /* bps */ 289 | u_int32_t scan_count; /* scan count during the previous period */ 290 | u_int32_t scan_duration; /* scan duration in ms */ 291 | } nstat_ifnet_desc_wifi_status; 292 | 293 | typedef struct nstat_ifnet_desc_link_status 294 | { 295 | u_int32_t link_status_type; 296 | union { 297 | nstat_ifnet_desc_cellular_status cellular; 298 | nstat_ifnet_desc_wifi_status wifi; 299 | } u; 300 | } nstat_ifnet_desc_link_status; 301 | 302 | #ifndef IF_DESCSIZE 303 | #define IF_DESCSIZE 128 304 | #endif 305 | typedef struct nstat_ifnet_descriptor 306 | { 307 | char name[IFNAMSIZ+1]; 308 | u_int32_t ifindex; 309 | u_int64_t threshold; 310 | unsigned int type; 311 | char description[IF_DESCSIZE]; 312 | nstat_ifnet_desc_link_status link_status; 313 | } nstat_ifnet_descriptor; 314 | 315 | typedef struct nstat_sysinfo_descriptor 316 | { 317 | u_int32_t flags; 318 | } nstat_sysinfo_descriptor; 319 | 320 | 321 | typedef struct nstat_msg_add_src 322 | { 323 | nstat_msg_hdr hdr; 324 | nstat_provider_id_t provider; 325 | u_int8_t param[]; 326 | } nstat_msg_add_src_req; 327 | 328 | typedef struct nstat_msg_add_all_srcs 329 | { 330 | nstat_msg_hdr hdr; 331 | nstat_provider_id_t provider; 332 | u_int64_t filter; 333 | nstat_event_flags_t events; 334 | pid_t target_pid; 335 | uuid_t target_uuid; 336 | } nstat_msg_add_all_srcs; 337 | 338 | typedef struct nstat_msg_src_added 339 | { 340 | nstat_msg_hdr hdr; 341 | nstat_provider_id_t provider; 342 | nstat_src_ref_t srcref; 343 | } nstat_msg_src_added; 344 | 345 | typedef struct nstat_msg_rem_src 346 | { 347 | nstat_msg_hdr hdr; 348 | nstat_src_ref_t srcref; 349 | } nstat_msg_rem_src_req; 350 | 351 | typedef struct nstat_msg_get_src_description 352 | { 353 | nstat_msg_hdr hdr; 354 | nstat_src_ref_t srcref; 355 | } nstat_msg_get_src_description; 356 | 357 | typedef struct nstat_msg_set_filter 358 | { 359 | nstat_msg_hdr hdr; 360 | nstat_src_ref_t srcref; 361 | u_int32_t filter; 362 | } nstat_msg_set_filter; 363 | 364 | typedef struct nstat_msg_src_description 365 | { 366 | nstat_msg_hdr hdr; 367 | nstat_src_ref_t srcref; 368 | nstat_event_flags_t event_flags; 369 | nstat_provider_id_t provider; 370 | u_int8_t data[]; 371 | } nstat_msg_src_description; 372 | 373 | typedef struct nstat_msg_query_src 374 | { 375 | nstat_msg_hdr hdr; 376 | nstat_src_ref_t srcref; 377 | } nstat_msg_query_src_req; 378 | 379 | typedef struct nstat_msg_src_counts 380 | { 381 | nstat_msg_hdr hdr; 382 | nstat_src_ref_t srcref; 383 | nstat_event_flags_t event_flags; 384 | nstat_counts counts; 385 | } nstat_msg_src_counts; 386 | 387 | typedef struct nstat_msg_src_update 388 | { 389 | nstat_msg_hdr hdr; 390 | nstat_src_ref_t srcref; 391 | nstat_event_flags_t event_flags; 392 | nstat_counts counts; 393 | nstat_provider_id_t provider; 394 | u_int8_t data[]; 395 | } nstat_msg_src_update; 396 | 397 | typedef struct nstat_msg_src_removed 398 | { 399 | nstat_msg_hdr hdr; 400 | nstat_src_ref_t srcref; 401 | } nstat_msg_src_removed; 402 | 403 | typedef struct nstat_sysinfo_counts 404 | { 405 | /* Counters */ 406 | u_int32_t nstat_sysinfo_len; 407 | u_int32_t pad; 408 | u_int8_t nstat_sysinfo_keyvals[]; 409 | } __attribute__((packed)) nstat_sysinfo_counts; 410 | 411 | typedef struct nstat_msg_sysinfo_counts 412 | { 413 | nstat_msg_hdr hdr; 414 | nstat_src_ref_t srcref; 415 | nstat_sysinfo_counts counts; 416 | } __attribute__((packed)) nstat_msg_sysinfo_counts; 417 | 418 | #pragma pack(pop) 419 | -------------------------------------------------------------------------------- /src/ntstat_kernel_4570.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "NTStatKernelStructHandler.hpp" 3 | 4 | // definitions from darwin-xnu/bsd/net/ntstat.h kernel header 5 | 6 | #include 7 | 8 | #include "ntstat_kernel_4570.h" 9 | 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | class NTStatKernel4570 : public NTStatKernelStructHandler 16 | { 17 | public: 18 | 19 | virtual bool isProviderTcp(uint64_t providerId){ 20 | return (NSTAT_PROVIDER_TCP_KERNEL == providerId)||(NSTAT_PROVIDER_TCP_USERLAND);} 21 | 22 | virtual bool isProviderUdp(uint64_t providerId) { 23 | return (NSTAT_PROVIDER_UDP_KERNEL == providerId)||(NSTAT_PROVIDER_UDP_USERLAND);} 24 | 25 | virtual bool isProviderInterface(uint64_t providerId) { return NSTAT_PROVIDER_IFNET == providerId; } 26 | 27 | //-------------------------------------------------------------------- 28 | // write GET_SRC_DESC message to dest 29 | //-------------------------------------------------------------------- 30 | virtual void writeSrcDesc(MsgDest &dest, uint64_t providerId, uint64_t srcRef ) 31 | { 32 | nstat_msg_get_src_description msg = nstat_msg_get_src_description(); 33 | 34 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_GET_SRC_DESC); 35 | 36 | msg.srcref = srcRef; 37 | 38 | dest.send(&msg.hdr, sizeof(msg)); 39 | } 40 | 41 | //-------------------------------------------------------------------- 42 | // write QUERY_SRC message to dest 43 | //-------------------------------------------------------------------- 44 | virtual void writeQuerySrc(MsgDest &dest, uint64_t srcRef) 45 | { 46 | nstat_msg_query_src_req msg = nstat_msg_query_src_req(); 47 | 48 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_QUERY_SRC); 49 | 50 | msg.srcref= srcRef; 51 | 52 | dest.send(&msg.hdr, sizeof(msg)); 53 | } 54 | 55 | //-------------------------------------------------------------------- 56 | // write ADD_ADD_SRCS message to dest 57 | //-------------------------------------------------------------------- 58 | virtual void writeAddAllSrc(MsgDest &dest, uint32_t providerId) 59 | { 60 | nstat_msg_add_all_srcs msg = nstat_msg_add_all_srcs(); 61 | 62 | NTSTAT_MSG_HDR(msg, dest, NSTAT_MSG_TYPE_ADD_ALL_SRCS); 63 | 64 | msg.provider = providerId ; 65 | 66 | dest.send(&msg.hdr, sizeof(msg)); 67 | } 68 | 69 | // xnu-3789 is first time we see split _KERNEL and _USERLAND 70 | 71 | virtual void writeAddAllTcpSrc(MsgDest &dest) { 72 | writeAddAllSrc(dest, NSTAT_PROVIDER_TCP_KERNEL); 73 | //writeAddAllSrc(dest, NSTAT_PROVIDER_TCP_USERLAND); 74 | } 75 | 76 | virtual void writeAddAllUdpSrc(MsgDest &dest) { 77 | writeAddAllSrc(dest, NSTAT_PROVIDER_UDP_KERNEL); 78 | //writeAddAllSrc(dest, NSTAT_PROVIDER_UDP_USERLAND); 79 | } 80 | 81 | virtual void writeAddAllInterfaces(MsgDest &dest) { 82 | writeAddAllSrc(dest, NSTAT_PROVIDER_IFNET); 83 | } 84 | 85 | 86 | //-------------------------------------------------------------------- 87 | // extract srcRef, providerId (if possible) from message 88 | //-------------------------------------------------------------------- 89 | virtual void getSrcRef(nstat_msg_hdr* msg, int structlen, uint64_t &srcRef, uint32_t &providerId) { 90 | switch(msg->type) 91 | { 92 | case NSTAT_MSG_TYPE_SRC_COUNTS: 93 | srcRef = ((nstat_msg_src_counts*)msg)->srcref; 94 | break; 95 | case NSTAT_MSG_TYPE_SRC_DESC: 96 | srcRef = ((nstat_msg_src_description*)msg)->srcref; 97 | providerId = ((nstat_msg_src_description*)msg)->provider; 98 | break; 99 | case NSTAT_MSG_TYPE_SRC_ADDED: 100 | srcRef = ((nstat_msg_src_added*)msg)->srcref; 101 | providerId = ((nstat_msg_src_added*)msg)->provider; 102 | break; 103 | case NSTAT_MSG_TYPE_SRC_REMOVED: 104 | srcRef = ((nstat_msg_src_removed*)msg)->srcref; 105 | break; 106 | default: 107 | //printf("E getSrcRef not implemented for type %d\n", msg->type); 108 | break; 109 | } 110 | } 111 | 112 | 113 | //-------------------------------------------------------------------- 114 | // populate dest with message data 115 | //-------------------------------------------------------------------- 116 | virtual bool readSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 117 | { 118 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 119 | if (msg->provider == NSTAT_PROVIDER_TCP_KERNEL || msg->provider == NSTAT_PROVIDER_TCP_USERLAND) { 120 | readTcpSrcDesc(hdr, structlen, dest); 121 | } else if (msg->provider == NSTAT_PROVIDER_UDP_KERNEL || msg->provider == NSTAT_PROVIDER_UDP_USERLAND) { 122 | readUdpSrcDesc(hdr, structlen, dest); 123 | } else { 124 | // ?? 125 | } 126 | return true; 127 | } 128 | 129 | 130 | //-------------------------------------------------------------------- 131 | // populate dest with message ifnet data 132 | //-------------------------------------------------------------------- 133 | /* 134 | virtual bool readSrcDesc(nstat_msg_hdr* hdr, int structlen, NTStatInterface* dest ) 135 | { 136 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 137 | if (msg->provider != NSTAT_PROVIDER_IFNET) return false; 138 | 139 | nstat_ifnet_descriptor* ifnet = (nstat_ifnet_descriptor*)msg->data; 140 | dest->name = string(ifnet->name); 141 | dest->description = string(ifnet->description); 142 | dest->ifindex = ifnet->ifindex; 143 | dest->type = ifnet->type; 144 | 145 | return false; 146 | }*/ 147 | 148 | //-------------------------------------------------------------------- 149 | // TCP: populate dest with message data 150 | //-------------------------------------------------------------------- 151 | virtual void readTcpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 152 | { 153 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 154 | nstat_tcp_descriptor*tcp = (nstat_tcp_descriptor*)msg->data; 155 | 156 | dest->key.ifindex = tcp->ifindex; 157 | dest->key.ipproto = IPPROTO_TCP; 158 | dest->key.isV6 = (tcp->local.v4.sin_family == AF_INET6); 159 | 160 | if (tcp->local.v4.sin_family == AF_INET6) 161 | { 162 | dest->key.lport = tcp->local.v6.sin6_port; 163 | dest->key.local.addr6 = tcp->local.v6.sin6_addr; 164 | dest->key.rport = tcp->remote.v6.sin6_port; 165 | dest->key.remote.addr6 = tcp->remote.v6.sin6_addr; 166 | } else { 167 | dest->key.lport = tcp->local.v4.sin_port; 168 | dest->key.rport = tcp->remote.v4.sin_port; 169 | dest->key.local.addr4 = tcp->local.v4.sin_addr; 170 | dest->key.remote.addr4 = tcp->remote.v4.sin_addr; 171 | } 172 | dest->states.txwindow = tcp->txwindow; 173 | dest->states.txcwindow = tcp->txcwindow; 174 | dest->states.state = tcp->state; 175 | 176 | dest->process.pid = tcp->pid; 177 | 178 | strcpy(dest->process.name, ((tcp->pid > 0 && tcp->pname[0]) ? tcp->pname : "")); 179 | } 180 | 181 | //-------------------------------------------------------------------- 182 | // UDP: populate dest with message data 183 | //-------------------------------------------------------------------- 184 | virtual void readUdpSrcDesc(nstat_msg_hdr*hdr, int structlen, NTStatStream* dest ) 185 | { 186 | nstat_msg_src_description *msg = (nstat_msg_src_description*)hdr; 187 | nstat_udp_descriptor*udp = (nstat_udp_descriptor*)msg->data; 188 | 189 | dest->key.ifindex = udp->ifindex; 190 | dest->key.ipproto = IPPROTO_UDP; 191 | dest->key.isV6 = (udp->local.v4.sin_family == AF_INET6); 192 | 193 | if (udp->local.v4.sin_family == AF_INET6) 194 | { 195 | dest->key.lport = udp->local.v6.sin6_port; 196 | dest->key.local.addr6 = udp->local.v6.sin6_addr; 197 | dest->key.rport = udp->remote.v6.sin6_port; 198 | dest->key.remote.addr6 = udp->remote.v6.sin6_addr; 199 | } else { 200 | dest->key.lport = udp->local.v4.sin_port; 201 | dest->key.rport = udp->remote.v4.sin_port; 202 | dest->key.local.addr4 = udp->local.v4.sin_addr; 203 | dest->key.remote.addr4 = udp->remote.v4.sin_addr; 204 | } 205 | 206 | dest->process.pid = udp->pid; 207 | strcpy(dest->process.name, ((udp->pid > 0 && udp->pname[0]) ? udp->pname : "")); 208 | } 209 | 210 | //-------------------------------------------------------------------- 211 | // populate dest with message counts data 212 | //-------------------------------------------------------------------- 213 | virtual void readCounts(nstat_msg_hdr*hdr, int structlen, NTStatCounters& dest ) 214 | { 215 | nstat_msg_src_counts *msg = (nstat_msg_src_counts*)hdr; 216 | dest.rxbytes = msg->counts.nstat_rxbytes; 217 | dest.txbytes = msg->counts.nstat_txbytes; 218 | dest.rxpackets = msg->counts.nstat_rxpackets; 219 | dest.txpackets = msg->counts.nstat_txpackets; 220 | 221 | dest.cell_rxbytes = msg->counts.nstat_cell_rxbytes; 222 | dest.cell_txbytes = msg->counts.nstat_cell_txbytes; 223 | 224 | dest.wifi_rxbytes = msg->counts.nstat_wifi_rxbytes; 225 | dest.wifi_txbytes = msg->counts.nstat_wifi_txbytes; 226 | 227 | dest.wired_rxbytes = msg->counts.nstat_wired_rxbytes; 228 | dest.wired_txbytes = msg->counts.nstat_wired_txbytes; 229 | } 230 | 231 | }; 232 | 233 | 234 | NTStatKernelStructHandler* NewNTStatKernel4570() { 235 | return new NTStatKernel4570(); 236 | } 237 | -------------------------------------------------------------------------------- /src/ntstat_kernel_4570.h: -------------------------------------------------------------------------------- 1 | // definitions from bsd/net/ntstat.h kernel header 2 | // https://github.com/apple/darwin-xnu 3 | // git checkout xnu-4570.1.46 4 | // High-Sierra 10.13 5 | 6 | // bsd/netinet/tcp.h 7 | struct tcp_conn_status { 8 | unsigned int probe_activated : 1; 9 | unsigned int write_probe_failed : 1; 10 | unsigned int read_probe_failed : 1; 11 | unsigned int conn_probe_failed : 1; 12 | }; 13 | #define IFNAMSIZ 16 14 | 15 | // bsd/netinet/in_stat.h 16 | typedef struct activity_bitmap { 17 | uint64_t start; /* Start timestamp using uptime */ 18 | uint64_t bitmap[2]; /* 128 bit map, each bit == 8 sec */ 19 | } activity_bitmap_t; 20 | 21 | // bsd/net/ntstat.h 22 | 23 | #pragma mark -- Common Data Structures -- 24 | 25 | #define __NSTAT_REVISION__ 9 26 | 27 | typedef u_int32_t nstat_provider_id_t; 28 | typedef u_int64_t nstat_src_ref_t; 29 | typedef u_int64_t nstat_event_flags_t; 30 | 31 | // The following event definitions are very provisional.. 32 | enum 33 | { 34 | NSTAT_EVENT_SRC_ADDED = 0x00000001 35 | ,NSTAT_EVENT_SRC_REMOVED = 0x00000002 36 | ,NSTAT_EVENT_SRC_QUERIED = 0x00000004 37 | ,NSTAT_EVENT_SRC_QUERIED_ALL = 0x00000008 38 | ,NSTAT_EVENT_SRC_WILL_CHANGE_STATE = 0x00000010 39 | ,NSTAT_EVENT_SRC_DID_CHANGE_STATE = 0x00000020 40 | ,NSTAT_EVENT_SRC_WILL_CHANGE_OWNER = 0x00000040 41 | ,NSTAT_EVENT_SRC_DID_CHANGE_OWNER = 0x00000080 42 | ,NSTAT_EVENT_SRC_WILL_CHANGE_PROPERTY = 0x00000100 43 | ,NSTAT_EVENT_SRC_DID_CHANGE_PROPERTY = 0x00000200 44 | }; 45 | 46 | typedef struct nstat_counts 47 | { 48 | /* Counters */ 49 | u_int64_t nstat_rxpackets __attribute__((aligned(sizeof(u_int64_t)))); 50 | u_int64_t nstat_rxbytes __attribute__((aligned(sizeof(u_int64_t)))); 51 | u_int64_t nstat_txpackets __attribute__((aligned(sizeof(u_int64_t)))); 52 | u_int64_t nstat_txbytes __attribute__((aligned(sizeof(u_int64_t)))); 53 | 54 | u_int64_t nstat_cell_rxbytes __attribute__((aligned(sizeof(u_int64_t)))); 55 | u_int64_t nstat_cell_txbytes __attribute__((aligned(sizeof(u_int64_t)))); 56 | u_int64_t nstat_wifi_rxbytes __attribute__((aligned(sizeof(u_int64_t)))); 57 | u_int64_t nstat_wifi_txbytes __attribute__((aligned(sizeof(u_int64_t)))); 58 | u_int64_t nstat_wired_rxbytes __attribute__((aligned(sizeof(u_int64_t)))); 59 | u_int64_t nstat_wired_txbytes __attribute__((aligned(sizeof(u_int64_t)))); 60 | 61 | u_int32_t nstat_rxduplicatebytes; 62 | u_int32_t nstat_rxoutoforderbytes; 63 | u_int32_t nstat_txretransmit; 64 | 65 | u_int32_t nstat_connectattempts; 66 | u_int32_t nstat_connectsuccesses; 67 | 68 | u_int32_t nstat_min_rtt; 69 | u_int32_t nstat_avg_rtt; 70 | u_int32_t nstat_var_rtt; 71 | } nstat_counts; 72 | 73 | #define NSTAT_SYSINFO_KEYVAL_STRING_MAXSIZE 24 74 | typedef struct nstat_sysinfo_keyval 75 | { 76 | u_int32_t nstat_sysinfo_key; 77 | u_int32_t nstat_sysinfo_flags; 78 | union { 79 | int64_t nstat_sysinfo_scalar; 80 | double nstat_sysinfo_distribution; 81 | u_int8_t nstat_sysinfo_string[NSTAT_SYSINFO_KEYVAL_STRING_MAXSIZE]; 82 | } u; 83 | u_int32_t nstat_sysinfo_valsize; 84 | u_int8_t reserved[4]; 85 | } nstat_sysinfo_keyval; 86 | 87 | #define NSTAT_SYSINFO_FLAG_SCALAR 0x0001 88 | #define NSTAT_SYSINFO_FLAG_DISTRIBUTION 0x0002 89 | #define NSTAT_SYSINFO_FLAG_STRING 0x0004 90 | 91 | #define NSTAT_MAX_MSG_SIZE 4096 92 | 93 | typedef struct nstat_sysinfo_counts 94 | { 95 | /* Counters */ 96 | u_int32_t nstat_sysinfo_len; 97 | u_int32_t pad; 98 | u_int8_t nstat_sysinfo_keyvals[]; 99 | } nstat_sysinfo_counts; 100 | 101 | enum 102 | { 103 | NSTAT_SYSINFO_KEY_MBUF_256B_TOTAL = 1 104 | ,NSTAT_SYSINFO_KEY_MBUF_2KB_TOTAL = 2 105 | ,NSTAT_SYSINFO_KEY_MBUF_4KB_TOTAL = 3 106 | ,NSTAT_SYSINFO_KEY_SOCK_MBCNT = 4 107 | ,NSTAT_SYSINFO_KEY_SOCK_ATMBLIMIT = 5 108 | ,NSTAT_SYSINFO_KEY_IPV4_AVGRTT = 6 109 | ,NSTAT_SYSINFO_KEY_IPV6_AVGRTT = 7 110 | ,NSTAT_SYSINFO_KEY_SEND_PLR = 8 111 | ,NSTAT_SYSINFO_KEY_RECV_PLR = 9 112 | ,NSTAT_SYSINFO_KEY_SEND_TLRTO = 10 113 | ,NSTAT_SYSINFO_KEY_SEND_REORDERRATE = 11 114 | ,NSTAT_SYSINFO_CONNECTION_ATTEMPTS = 12 115 | ,NSTAT_SYSINFO_CONNECTION_ACCEPTS = 13 116 | ,NSTAT_SYSINFO_ECN_CLIENT_SETUP = 14 117 | ,NSTAT_SYSINFO_ECN_SERVER_SETUP = 15 118 | ,NSTAT_SYSINFO_ECN_CLIENT_SUCCESS = 16 119 | ,NSTAT_SYSINFO_ECN_SERVER_SUCCESS = 17 120 | ,NSTAT_SYSINFO_ECN_NOT_SUPPORTED = 18 121 | ,NSTAT_SYSINFO_ECN_LOST_SYN = 19 122 | ,NSTAT_SYSINFO_ECN_LOST_SYNACK = 20 123 | ,NSTAT_SYSINFO_ECN_RECV_CE = 21 124 | ,NSTAT_SYSINFO_ECN_RECV_ECE = 22 125 | ,NSTAT_SYSINFO_ECN_SENT_ECE = 23 126 | ,NSTAT_SYSINFO_ECN_CONN_RECV_CE = 24 127 | ,NSTAT_SYSINFO_ECN_CONN_PLNOCE = 25 128 | ,NSTAT_SYSINFO_ECN_CONN_PL_CE = 26 129 | ,NSTAT_SYSINFO_ECN_CONN_NOPL_CE = 27 130 | ,NSTAT_SYSINFO_MBUF_16KB_TOTAL = 28 131 | ,NSTAT_SYSINFO_ECN_CLIENT_ENABLED = 29 132 | ,NSTAT_SYSINFO_ECN_SERVER_ENABLED = 30 133 | ,NSTAT_SYSINFO_ECN_CONN_RECV_ECE = 31 134 | ,NSTAT_SYSINFO_MBUF_MEM_RELEASED = 32 135 | ,NSTAT_SYSINFO_MBUF_DRAIN_CNT = 33 136 | ,NSTAT_SYSINFO_TFO_SYN_DATA_RCV = 34 137 | ,NSTAT_SYSINFO_TFO_COOKIE_REQ_RCV = 35 138 | ,NSTAT_SYSINFO_TFO_COOKIE_SENT = 36 139 | ,NSTAT_SYSINFO_TFO_COOKIE_INVALID = 37 140 | ,NSTAT_SYSINFO_TFO_COOKIE_REQ = 38 141 | ,NSTAT_SYSINFO_TFO_COOKIE_RCV = 39 142 | ,NSTAT_SYSINFO_TFO_SYN_DATA_SENT = 40 143 | ,NSTAT_SYSINFO_TFO_SYN_DATA_ACKED = 41 144 | ,NSTAT_SYSINFO_TFO_SYN_LOSS = 42 145 | ,NSTAT_SYSINFO_TFO_BLACKHOLE = 43 146 | ,NSTAT_SYSINFO_ECN_FALLBACK_SYNLOSS = 44 147 | ,NSTAT_SYSINFO_ECN_FALLBACK_REORDER = 45 148 | ,NSTAT_SYSINFO_ECN_FALLBACK_CE = 46 149 | ,NSTAT_SYSINFO_ECN_IFNET_TYPE = 47 150 | ,NSTAT_SYSINFO_ECN_IFNET_PROTO = 48 151 | ,NSTAT_SYSINFO_ECN_IFNET_CLIENT_SETUP = 49 152 | ,NSTAT_SYSINFO_ECN_IFNET_SERVER_SETUP = 50 153 | ,NSTAT_SYSINFO_ECN_IFNET_CLIENT_SUCCESS = 51 154 | ,NSTAT_SYSINFO_ECN_IFNET_SERVER_SUCCESS = 52 155 | ,NSTAT_SYSINFO_ECN_IFNET_PEER_NOSUPPORT = 53 156 | ,NSTAT_SYSINFO_ECN_IFNET_SYN_LOST = 54 157 | ,NSTAT_SYSINFO_ECN_IFNET_SYNACK_LOST = 55 158 | ,NSTAT_SYSINFO_ECN_IFNET_RECV_CE = 56 159 | ,NSTAT_SYSINFO_ECN_IFNET_RECV_ECE = 57 160 | ,NSTAT_SYSINFO_ECN_IFNET_SENT_ECE = 58 161 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_RECV_CE = 59 162 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_RECV_ECE = 60 163 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_PLNOCE = 61 164 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_PLCE = 62 165 | ,NSTAT_SYSINFO_ECN_IFNET_CONN_NOPLCE = 63 166 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_SYNLOSS = 64 167 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_REORDER = 65 168 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_CE = 66 169 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RTT_AVG = 67 170 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RTT_VAR = 68 171 | ,NSTAT_SYSINFO_ECN_IFNET_ON_OOPERCENT = 69 172 | ,NSTAT_SYSINFO_ECN_IFNET_ON_SACK_EPISODE = 70 173 | ,NSTAT_SYSINFO_ECN_IFNET_ON_REORDER_PERCENT = 71 174 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RXMIT_PERCENT = 72 175 | ,NSTAT_SYSINFO_ECN_IFNET_ON_RXMIT_DROP = 73 176 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RTT_AVG = 74 177 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RTT_VAR = 75 178 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_OOPERCENT = 76 179 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_SACK_EPISODE = 77 180 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_REORDER_PERCENT = 78 181 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RXMIT_PERCENT = 79 182 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_RXMIT_DROP = 80 183 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_TXPKTS = 81 184 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_RXMTPKTS = 82 185 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_RXPKTS = 83 186 | ,NSTAT_SYSINFO_ECN_IFNET_ON_TOTAL_OOPKTS = 84 187 | ,NSTAT_SYSINFO_ECN_IFNET_ON_DROP_RST = 85 188 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_TXPKTS = 86 189 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_RXMTPKTS = 87 190 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_RXPKTS = 88 191 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_TOTAL_OOPKTS = 89 192 | ,NSTAT_SYSINFO_ECN_IFNET_OFF_DROP_RST = 90 193 | ,NSTAT_SYSINFO_ECN_IFNET_TOTAL_CONN = 91 194 | ,NSTAT_SYSINFO_TFO_COOKIE_WRONG = 92 195 | ,NSTAT_SYSINFO_TFO_NO_COOKIE_RCV = 93 196 | ,NSTAT_SYSINFO_TFO_HEURISTICS_DISABLE = 94 197 | ,NSTAT_SYSINFO_TFO_SEND_BLACKHOLE = 95 198 | ,NSTAT_SYSINFO_KEY_SOCK_MBFLOOR = 96 199 | ,NSTAT_SYSINFO_IFNET_UNSENT_DATA = 97 200 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_DROPRST = 98 201 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_DROPRXMT = 99 202 | ,NSTAT_SYSINFO_LIM_IFNET_SIGNATURE = 100 203 | ,NSTAT_SYSINFO_LIM_IFNET_DL_MAX_BANDWIDTH = 101 204 | ,NSTAT_SYSINFO_LIM_IFNET_UL_MAX_BANDWIDTH = 102 205 | ,NSTAT_SYSINFO_LIM_IFNET_PACKET_LOSS_PERCENT = 103 206 | ,NSTAT_SYSINFO_LIM_IFNET_PACKET_OOO_PERCENT = 104 207 | ,NSTAT_SYSINFO_LIM_IFNET_RTT_VARIANCE = 105 208 | ,NSTAT_SYSINFO_LIM_IFNET_RTT_MIN = 106 209 | ,NSTAT_SYSINFO_LIM_IFNET_RTT_AVG = 107 210 | ,NSTAT_SYSINFO_LIM_IFNET_CONN_TIMEOUT_PERCENT = 108 211 | ,NSTAT_SYSINFO_LIM_IFNET_DL_DETECTED = 109 212 | ,NSTAT_SYSINFO_LIM_IFNET_UL_DETECTED = 110 213 | ,NSTAT_SYSINFO_LIM_IFNET_TYPE = 111 214 | 215 | ,NSTAT_SYSINFO_API_IF_FLTR_ATTACH = 112 216 | ,NSTAT_SYSINFO_API_IF_FLTR_ATTACH_OS = 113 217 | ,NSTAT_SYSINFO_API_IP_FLTR_ADD = 114 218 | ,NSTAT_SYSINFO_API_IP_FLTR_ADD_OS = 115 219 | ,NSTAT_SYSINFO_API_SOCK_FLTR_ATTACH = 116 220 | ,NSTAT_SYSINFO_API_SOCK_FLTR_ATTACH_OS = 117 221 | 222 | ,NSTAT_SYSINFO_API_SOCK_ALLOC_TOTAL = 118 223 | ,NSTAT_SYSINFO_API_SOCK_ALLOC_KERNEL = 119 224 | ,NSTAT_SYSINFO_API_SOCK_ALLOC_KERNEL_OS = 120 225 | ,NSTAT_SYSINFO_API_SOCK_NECP_CLIENTUUID = 121 226 | 227 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_LOCAL = 122 228 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_ROUTE = 123 229 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_INET = 124 230 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_INET6 = 125 231 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_SYSTEM = 126 232 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_MULTIPATH = 127 233 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_KEY = 128 234 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_NDRV = 129 235 | ,NSTAT_SYSINFO_API_SOCK_DOMAIN_OTHER = 130 236 | 237 | ,NSTAT_SYSINFO_API_SOCK_INET_STREAM= 131 238 | ,NSTAT_SYSINFO_API_SOCK_INET_DGRAM = 132 239 | ,NSTAT_SYSINFO_API_SOCK_INET_DGRAM_CONNECTED = 133 240 | ,NSTAT_SYSINFO_API_SOCK_INET_DGRAM_DNS = 134 241 | ,NSTAT_SYSINFO_API_SOCK_INET_DGRAM_NO_DATA = 135 242 | 243 | ,NSTAT_SYSINFO_API_SOCK_INET6_STREAM= 136 244 | ,NSTAT_SYSINFO_API_SOCK_INET6_DGRAM = 137 245 | ,NSTAT_SYSINFO_API_SOCK_INET6_DGRAM_CONNECTED = 138 246 | ,NSTAT_SYSINFO_API_SOCK_INET6_DGRAM_DNS = 139 247 | ,NSTAT_SYSINFO_API_SOCK_INET6_DGRAM_NO_DATA = 140 248 | 249 | ,NSTAT_SYSINFO_API_SOCK_INET_MCAST_JOIN = 141 250 | ,NSTAT_SYSINFO_API_SOCK_INET_MCAST_JOIN_OS = 142 251 | 252 | ,NSTAT_SYSINFO_API_SOCK_INET6_STREAM_EXTHDR_IN = 143 253 | ,NSTAT_SYSINFO_API_SOCK_INET6_STREAM_EXTHDR_OUT = 144 254 | ,NSTAT_SYSINFO_API_SOCK_INET6_DGRAM_EXTHDR_IN = 145 255 | ,NSTAT_SYSINFO_API_SOCK_INET6_DGRAM_EXTHDR_OUT = 146 256 | 257 | ,NSTAT_SYSINFO_API_NEXUS_FLOW_INET_STREAM = 147 258 | ,NSTAT_SYSINFO_API_NEXUS_FLOW_INET_DATAGRAM = 148 259 | 260 | ,NSTAT_SYSINFO_API_NEXUS_FLOW_INET6_STREAM = 149 261 | ,NSTAT_SYSINFO_API_NEXUS_FLOW_INET6_DATAGRAM = 150 262 | 263 | ,NSTAT_SYSINFO_API_IFNET_ALLOC = 151 264 | ,NSTAT_SYSINFO_API_IFNET_ALLOC_OS = 152 265 | 266 | ,NSTAT_SYSINFO_API_PF_ADDRULE = 153 267 | ,NSTAT_SYSINFO_API_PF_ADDRULE_OS = 154 268 | 269 | ,NSTAT_SYSINFO_API_VMNET_START = 155 270 | 271 | ,NSTAT_SYSINFO_API_IF_NETAGENT_ENABLED = 156 272 | 273 | ,NSTAT_SYSINFO_API_REPORT_INTERVAL = 157 274 | 275 | ,NSTAT_SYSINFO_MPTCP_HANDOVER_ATTEMPT = 158 276 | ,NSTAT_SYSINFO_MPTCP_INTERACTIVE_ATTEMPT = 159 277 | ,NSTAT_SYSINFO_MPTCP_AGGREGATE_ATTEMPT = 160 278 | ,NSTAT_SYSINFO_MPTCP_FP_HANDOVER_ATTEMPT = 161 /* _FP_ stands for first-party */ 279 | ,NSTAT_SYSINFO_MPTCP_FP_INTERACTIVE_ATTEMPT = 162 280 | ,NSTAT_SYSINFO_MPTCP_FP_AGGREGATE_ATTEMPT = 163 281 | ,NSTAT_SYSINFO_MPTCP_HEURISTIC_FALLBACK = 164 282 | ,NSTAT_SYSINFO_MPTCP_FP_HEURISTIC_FALLBACK = 165 283 | ,NSTAT_SYSINFO_MPTCP_HANDOVER_SUCCESS_WIFI = 166 284 | ,NSTAT_SYSINFO_MPTCP_HANDOVER_SUCCESS_CELL = 167 285 | ,NSTAT_SYSINFO_MPTCP_INTERACTIVE_SUCCESS = 168 286 | ,NSTAT_SYSINFO_MPTCP_AGGREGATE_SUCCESS = 169 287 | ,NSTAT_SYSINFO_MPTCP_FP_HANDOVER_SUCCESS_WIFI = 170 288 | ,NSTAT_SYSINFO_MPTCP_FP_HANDOVER_SUCCESS_CELL = 171 289 | ,NSTAT_SYSINFO_MPTCP_FP_INTERACTIVE_SUCCESS = 172 290 | ,NSTAT_SYSINFO_MPTCP_FP_AGGREGATE_SUCCESS = 173 291 | ,NSTAT_SYSINFO_MPTCP_HANDOVER_CELL_FROM_WIFI = 174 292 | ,NSTAT_SYSINFO_MPTCP_HANDOVER_WIFI_FROM_CELL = 175 293 | ,NSTAT_SYSINFO_MPTCP_INTERACTIVE_CELL_FROM_WIFI = 176 294 | ,NSTAT_SYSINFO_MPTCP_HANDOVER_CELL_BYTES = 177 295 | ,NSTAT_SYSINFO_MPTCP_INTERACTIVE_CELL_BYTES = 178 296 | ,NSTAT_SYSINFO_MPTCP_AGGREGATE_CELL_BYTES = 179 297 | ,NSTAT_SYSINFO_MPTCP_HANDOVER_ALL_BYTES = 180 298 | ,NSTAT_SYSINFO_MPTCP_INTERACTIVE_ALL_BYTES = 181 299 | ,NSTAT_SYSINFO_MPTCP_AGGREGATE_ALL_BYTES = 182 300 | ,NSTAT_SYSINFO_MPTCP_BACK_TO_WIFI = 183 301 | ,NSTAT_SYSINFO_MPTCP_WIFI_PROXY = 184 302 | ,NSTAT_SYSINFO_MPTCP_CELL_PROXY = 185 303 | ,NSTAT_SYSINFO_ECN_IFNET_FALLBACK_SYNRST = 186 304 | 305 | // NSTAT_SYSINFO_ENUM_VERSION must be updated any time a value is added 306 | #define NSTAT_SYSINFO_ENUM_VERSION 20170623 307 | }; 308 | 309 | #define NSTAT_SYSINFO_API_FIRST NSTAT_SYSINFO_API_IF_FLTR_ATTACH 310 | #define NSTAT_SYSINFO_API_LAST NSTAT_SYSINFO_API_REPORT_INTERVAL 311 | 312 | #pragma mark -- Network Statistics Providers -- 313 | 314 | 315 | // Interface properties 316 | 317 | #define NSTAT_IFNET_IS_UNKNOWN_TYPE 0x01 318 | #define NSTAT_IFNET_IS_LOOPBACK 0x02 319 | #define NSTAT_IFNET_IS_CELLULAR 0x04 320 | #define NSTAT_IFNET_IS_WIFI 0x08 321 | #define NSTAT_IFNET_IS_WIRED 0x10 322 | #define NSTAT_IFNET_IS_AWDL 0x20 323 | #define NSTAT_IFNET_IS_EXPENSIVE 0x40 324 | #define NSTAT_IFNET_IS_VPN 0x80 325 | #define NSTAT_IFNET_VIA_CELLFALLBACK 0x100 326 | // Temporary properties of use for bringing up userland providers 327 | #define NSTAT_IFNET_ROUTE_VALUE_UNOBTAINABLE 0x1000 328 | #define NSTAT_IFNET_FLOWSWITCH_VALUE_UNOBTAINABLE 0x2000 329 | 330 | 331 | enum 332 | { 333 | NSTAT_PROVIDER_NONE = 0 334 | ,NSTAT_PROVIDER_ROUTE = 1 335 | ,NSTAT_PROVIDER_TCP_KERNEL = 2 336 | ,NSTAT_PROVIDER_TCP_USERLAND = 3 337 | ,NSTAT_PROVIDER_UDP_KERNEL = 4 338 | ,NSTAT_PROVIDER_UDP_USERLAND = 5 339 | ,NSTAT_PROVIDER_IFNET = 6 340 | ,NSTAT_PROVIDER_SYSINFO = 7 341 | }; 342 | #define NSTAT_PROVIDER_LAST NSTAT_PROVIDER_SYSINFO 343 | #define NSTAT_PROVIDER_COUNT (NSTAT_PROVIDER_LAST+1) 344 | 345 | typedef struct nstat_route_add_param 346 | { 347 | union 348 | { 349 | struct sockaddr_in v4; 350 | struct sockaddr_in6 v6; 351 | } dst; 352 | union 353 | { 354 | struct sockaddr_in v4; 355 | struct sockaddr_in6 v6; 356 | } mask; 357 | u_int32_t ifindex; 358 | } nstat_route_add_param; 359 | 360 | typedef struct nstat_tcp_add_param 361 | { 362 | union 363 | { 364 | struct sockaddr_in v4; 365 | struct sockaddr_in6 v6; 366 | } local; 367 | union 368 | { 369 | struct sockaddr_in v4; 370 | struct sockaddr_in6 v6; 371 | } remote; 372 | } nstat_tcp_add_param; 373 | 374 | typedef struct nstat_tcp_descriptor 375 | { 376 | u_int64_t upid __attribute__((aligned(sizeof(u_int64_t)))); 377 | u_int64_t eupid __attribute__((aligned(sizeof(u_int64_t)))); 378 | u_int64_t start_timestamp __attribute__((aligned(sizeof(u_int64_t)))); 379 | u_int64_t timestamp __attribute__((aligned(sizeof(u_int64_t)))); 380 | 381 | activity_bitmap_t activity_bitmap; 382 | 383 | u_int32_t ifindex; 384 | u_int32_t state; 385 | 386 | u_int32_t sndbufsize; 387 | u_int32_t sndbufused; 388 | u_int32_t rcvbufsize; 389 | u_int32_t rcvbufused; 390 | u_int32_t txunacked; 391 | u_int32_t txwindow; 392 | u_int32_t txcwindow; 393 | u_int32_t traffic_class; 394 | u_int32_t traffic_mgt_flags; 395 | 396 | u_int32_t pid; 397 | u_int32_t epid; 398 | 399 | union 400 | { 401 | struct sockaddr_in v4; 402 | struct sockaddr_in6 v6; 403 | } local; 404 | 405 | union 406 | { 407 | struct sockaddr_in v4; 408 | struct sockaddr_in6 v6; 409 | } remote; 410 | 411 | char cc_algo[16]; 412 | char pname[64]; 413 | 414 | uuid_t uuid; 415 | uuid_t euuid; 416 | uuid_t vuuid; 417 | union { 418 | struct tcp_conn_status connstatus; 419 | // On armv7k, tcp_conn_status is 1 byte instead of 4 420 | uint8_t __pad_connstatus[4]; 421 | }; 422 | uint16_t ifnet_properties __attribute__((aligned(4))); 423 | 424 | u_int8_t reserved[6]; 425 | } nstat_tcp_descriptor; 426 | 427 | typedef struct nstat_tcp_add_param nstat_udp_add_param; 428 | 429 | typedef struct nstat_udp_descriptor 430 | { 431 | u_int64_t upid __attribute__((aligned(sizeof(u_int64_t)))); 432 | u_int64_t eupid __attribute__((aligned(sizeof(u_int64_t)))); 433 | u_int64_t start_timestamp __attribute__((aligned(sizeof(u_int64_t)))); 434 | u_int64_t timestamp __attribute__((aligned(sizeof(u_int64_t)))); 435 | 436 | activity_bitmap_t activity_bitmap; 437 | 438 | union 439 | { 440 | struct sockaddr_in v4; 441 | struct sockaddr_in6 v6; 442 | } local; 443 | 444 | union 445 | { 446 | struct sockaddr_in v4; 447 | struct sockaddr_in6 v6; 448 | } remote; 449 | 450 | u_int32_t ifindex; 451 | 452 | u_int32_t rcvbufsize; 453 | u_int32_t rcvbufused; 454 | u_int32_t traffic_class; 455 | 456 | u_int32_t pid; 457 | char pname[64]; 458 | u_int32_t epid; 459 | 460 | uuid_t uuid; 461 | uuid_t euuid; 462 | uuid_t vuuid; 463 | uint16_t ifnet_properties; 464 | 465 | u_int8_t reserved[6]; 466 | } nstat_udp_descriptor; 467 | 468 | typedef struct nstat_route_descriptor 469 | { 470 | u_int64_t id __attribute__((aligned(sizeof(u_int64_t)))); 471 | u_int64_t parent_id __attribute__((aligned(sizeof(u_int64_t)))); 472 | u_int64_t gateway_id __attribute__((aligned(sizeof(u_int64_t)))); 473 | 474 | union 475 | { 476 | struct sockaddr_in v4; 477 | struct sockaddr_in6 v6; 478 | struct sockaddr sa; 479 | } dst; 480 | 481 | union 482 | { 483 | struct sockaddr_in v4; 484 | struct sockaddr_in6 v6; 485 | struct sockaddr sa; 486 | } mask; 487 | 488 | union 489 | { 490 | struct sockaddr_in v4; 491 | struct sockaddr_in6 v6; 492 | struct sockaddr sa; 493 | } gateway; 494 | 495 | u_int32_t ifindex; 496 | u_int32_t flags; 497 | 498 | u_int8_t reserved[4]; 499 | } nstat_route_descriptor; 500 | 501 | typedef struct nstat_ifnet_add_param 502 | { 503 | u_int64_t threshold __attribute__((aligned(sizeof(u_int64_t)))); 504 | u_int32_t ifindex; 505 | 506 | u_int8_t reserved[4]; 507 | } nstat_ifnet_add_param; 508 | 509 | typedef struct nstat_ifnet_desc_cellular_status 510 | { 511 | u_int32_t valid_bitmask; /* indicates which fields are valid */ 512 | #define NSTAT_IFNET_DESC_CELL_LINK_QUALITY_METRIC_VALID 0x1 513 | #define NSTAT_IFNET_DESC_CELL_UL_EFFECTIVE_BANDWIDTH_VALID 0x2 514 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_BANDWIDTH_VALID 0x4 515 | #define NSTAT_IFNET_DESC_CELL_UL_MIN_LATENCY_VALID 0x8 516 | #define NSTAT_IFNET_DESC_CELL_UL_EFFECTIVE_LATENCY_VALID 0x10 517 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_LATENCY_VALID 0x20 518 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_VALID 0x40 519 | #define NSTAT_IFNET_DESC_CELL_UL_BYTES_LOST_VALID 0x80 520 | #define NSTAT_IFNET_DESC_CELL_UL_MIN_QUEUE_SIZE_VALID 0x100 521 | #define NSTAT_IFNET_DESC_CELL_UL_AVG_QUEUE_SIZE_VALID 0x200 522 | #define NSTAT_IFNET_DESC_CELL_UL_MAX_QUEUE_SIZE_VALID 0x400 523 | #define NSTAT_IFNET_DESC_CELL_DL_EFFECTIVE_BANDWIDTH_VALID 0x800 524 | #define NSTAT_IFNET_DESC_CELL_DL_MAX_BANDWIDTH_VALID 0x1000 525 | #define NSTAT_IFNET_DESC_CELL_CONFIG_INACTIVITY_TIME_VALID 0x2000 526 | #define NSTAT_IFNET_DESC_CELL_CONFIG_BACKOFF_TIME_VALID 0x4000 527 | #define NSTAT_IFNET_DESC_CELL_MSS_RECOMMENDED_VALID 0x8000 528 | u_int32_t link_quality_metric; 529 | u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on 530 | current activity (bps) */ 531 | u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth 532 | (bps) */ 533 | u_int32_t ul_min_latency; /* min expected uplink latency for first hop 534 | (ms) */ 535 | u_int32_t ul_effective_latency; /* current expected uplink latency for 536 | first hop (ms) */ 537 | u_int32_t ul_max_latency; /* max expected uplink latency first hop 538 | (ms) */ 539 | u_int32_t ul_retxt_level; /* Retransmission metric */ 540 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_NONE 1 541 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_LOW 2 542 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_MEDIUM 3 543 | #define NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_HIGH 4 544 | 545 | u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 546 | format */ 547 | u_int32_t ul_min_queue_size; /* minimum bytes in queue */ 548 | u_int32_t ul_avg_queue_size; /* average bytes in queue */ 549 | u_int32_t ul_max_queue_size; /* maximum bytes in queue */ 550 | u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based 551 | on current activity (bps) */ 552 | u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth 553 | (bps) */ 554 | u_int32_t config_inactivity_time; /* ms */ 555 | u_int32_t config_backoff_time; /* new connections backoff time in ms */ 556 | #define NSTAT_IFNET_DESC_MSS_RECOMMENDED_NONE 0x0 557 | #define NSTAT_IFNET_DESC_MSS_RECOMMENDED_MEDIUM 0x1 558 | #define NSTAT_IFNET_DESC_MSS_RECOMMENDED_LOW 0x2 559 | u_int16_t mss_recommended; /* recommended MSS */ 560 | u_int8_t reserved[2]; 561 | } nstat_ifnet_desc_cellular_status; 562 | 563 | typedef struct nstat_ifnet_desc_wifi_status { 564 | u_int32_t valid_bitmask; 565 | #define NSTAT_IFNET_DESC_WIFI_LINK_QUALITY_METRIC_VALID 0x1 566 | #define NSTAT_IFNET_DESC_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID 0x2 567 | #define NSTAT_IFNET_DESC_WIFI_UL_MAX_BANDWIDTH_VALID 0x4 568 | #define NSTAT_IFNET_DESC_WIFI_UL_MIN_LATENCY_VALID 0x8 569 | #define NSTAT_IFNET_DESC_WIFI_UL_EFFECTIVE_LATENCY_VALID 0x10 570 | #define NSTAT_IFNET_DESC_WIFI_UL_MAX_LATENCY_VALID 0x20 571 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_VALID 0x40 572 | #define NSTAT_IFNET_DESC_WIFI_UL_ERROR_RATE_VALID 0x80 573 | #define NSTAT_IFNET_DESC_WIFI_UL_BYTES_LOST_VALID 0x100 574 | #define NSTAT_IFNET_DESC_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID 0x200 575 | #define NSTAT_IFNET_DESC_WIFI_DL_MAX_BANDWIDTH_VALID 0x400 576 | #define NSTAT_IFNET_DESC_WIFI_DL_MIN_LATENCY_VALID 0x800 577 | #define NSTAT_IFNET_DESC_WIFI_DL_EFFECTIVE_LATENCY_VALID 0x1000 578 | #define NSTAT_IFNET_DESC_WIFI_DL_MAX_LATENCY_VALID 0x2000 579 | #define NSTAT_IFNET_DESC_WIFI_DL_ERROR_RATE_VALID 0x4000 580 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_VALID 0x8000 581 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_MULTICAST_RATE_VALID 0x10000 582 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_SCAN_COUNT_VALID 0x20000 583 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_SCAN_DURATION_VALID 0x40000 584 | u_int32_t link_quality_metric; /* link quality metric */ 585 | u_int32_t ul_effective_bandwidth; /* Measured uplink bandwidth based on 586 | current activity (bps) */ 587 | u_int32_t ul_max_bandwidth; /* Maximum supported uplink bandwidth 588 | (bps) */ 589 | u_int32_t ul_min_latency; /* min expected uplink latency for first hop 590 | (ms) */ 591 | u_int32_t ul_effective_latency; /* current expected uplink latency for 592 | first hop (ms) */ 593 | u_int32_t ul_max_latency; /* max expected uplink latency for first hop 594 | (ms) */ 595 | u_int32_t ul_retxt_level; /* Retransmission metric */ 596 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_NONE 1 597 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_LOW 2 598 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_MEDIUM 3 599 | #define NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_HIGH 4 600 | 601 | u_int32_t ul_bytes_lost; /* % of total bytes lost on uplink in Q10 602 | format */ 603 | u_int32_t ul_error_rate; /* % of bytes dropped on uplink after many 604 | retransmissions in Q10 format */ 605 | u_int32_t dl_effective_bandwidth; /* Measured downlink bandwidth based 606 | on current activity (bps) */ 607 | u_int32_t dl_max_bandwidth; /* Maximum supported downlink bandwidth 608 | (bps) */ 609 | /* 610 | * The download latency values indicate the time AP may have to wait 611 | * for the driver to receive the packet. These values give the range 612 | * of expected latency mainly due to co-existence events and channel 613 | * hopping where the interface becomes unavailable. 614 | */ 615 | u_int32_t dl_min_latency; /* min expected latency for first hop in ms */ 616 | u_int32_t dl_effective_latency; /* current expected latency for first 617 | hop in ms */ 618 | u_int32_t dl_max_latency; /* max expected latency for first hop in ms */ 619 | u_int32_t dl_error_rate; /* % of CRC or other errors in Q10 format */ 620 | u_int32_t config_frequency; /* 2.4 or 5 GHz */ 621 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_2_4_GHZ 1 622 | #define NSTAT_IFNET_DESC_WIFI_CONFIG_FREQUENCY_5_0_GHZ 2 623 | u_int32_t config_multicast_rate; /* bps */ 624 | u_int32_t scan_count; /* scan count during the previous period */ 625 | u_int32_t scan_duration; /* scan duration in ms */ 626 | } nstat_ifnet_desc_wifi_status; 627 | 628 | enum 629 | { 630 | NSTAT_IFNET_DESC_LINK_STATUS_TYPE_NONE = 0 631 | ,NSTAT_IFNET_DESC_LINK_STATUS_TYPE_CELLULAR = 1 632 | ,NSTAT_IFNET_DESC_LINK_STATUS_TYPE_WIFI = 2 633 | ,NSTAT_IFNET_DESC_LINK_STATUS_TYPE_ETHERNET = 3 634 | }; 635 | 636 | typedef struct nstat_ifnet_desc_link_status 637 | { 638 | u_int32_t link_status_type; 639 | union { 640 | nstat_ifnet_desc_cellular_status cellular; 641 | nstat_ifnet_desc_wifi_status wifi; 642 | } u; 643 | } nstat_ifnet_desc_link_status; 644 | 645 | #ifndef IF_DESCSIZE 646 | #define IF_DESCSIZE 128 647 | #endif 648 | typedef struct nstat_ifnet_descriptor 649 | { 650 | u_int64_t threshold __attribute__((aligned(sizeof(u_int64_t)))); 651 | u_int32_t ifindex; 652 | nstat_ifnet_desc_link_status link_status; 653 | unsigned int type; 654 | char description[IF_DESCSIZE]; 655 | char name[IFNAMSIZ+1]; 656 | u_int8_t reserved[3]; 657 | } nstat_ifnet_descriptor; 658 | 659 | typedef struct nstat_sysinfo_descriptor 660 | { 661 | u_int32_t flags; 662 | } nstat_sysinfo_descriptor; 663 | 664 | typedef struct nstat_sysinfo_add_param 665 | { 666 | /* To indicate which system level information should be collected */ 667 | u_int32_t flags; 668 | } nstat_sysinfo_add_param; 669 | 670 | #define NSTAT_SYSINFO_MBUF_STATS 0x0001 671 | #define NSTAT_SYSINFO_TCP_STATS 0x0002 672 | #define NSTAT_SYSINFO_IFNET_ECN_STATS 0x0003 673 | #define NSTAT_SYSINFO_LIM_STATS 0x0004 /* Low Internet mode stats */ 674 | #define NSTAT_SYSINFO_NET_API_STATS 0x0005 /* API and KPI stats */ 675 | 676 | #pragma mark -- Network Statistics User Client -- 677 | 678 | #define NET_STAT_CONTROL_NAME "com.apple.network.statistics" 679 | 680 | enum 681 | { 682 | // generic response messages 683 | NSTAT_MSG_TYPE_SUCCESS = 0 684 | ,NSTAT_MSG_TYPE_ERROR = 1 685 | 686 | // Requests 687 | ,NSTAT_MSG_TYPE_ADD_SRC = 1001 688 | ,NSTAT_MSG_TYPE_ADD_ALL_SRCS = 1002 689 | ,NSTAT_MSG_TYPE_REM_SRC = 1003 690 | ,NSTAT_MSG_TYPE_QUERY_SRC = 1004 691 | ,NSTAT_MSG_TYPE_GET_SRC_DESC = 1005 692 | ,NSTAT_MSG_TYPE_SET_FILTER = 1006 693 | ,NSTAT_MSG_TYPE_GET_UPDATE = 1007 694 | ,NSTAT_MSG_TYPE_SUBSCRIBE_SYSINFO = 1008 695 | 696 | // Responses/Notfications 697 | ,NSTAT_MSG_TYPE_SRC_ADDED = 10001 698 | ,NSTAT_MSG_TYPE_SRC_REMOVED = 10002 699 | ,NSTAT_MSG_TYPE_SRC_DESC = 10003 700 | ,NSTAT_MSG_TYPE_SRC_COUNTS = 10004 701 | ,NSTAT_MSG_TYPE_SYSINFO_COUNTS = 10005 702 | ,NSTAT_MSG_TYPE_SRC_UPDATE = 10006 703 | }; 704 | 705 | enum 706 | { 707 | NSTAT_SRC_REF_ALL = 0xffffffffffffffffULL 708 | ,NSTAT_SRC_REF_INVALID = 0 709 | }; 710 | 711 | /* Source-level filters */ 712 | enum 713 | { 714 | NSTAT_FILTER_NOZEROBYTES = 0x00000001 715 | }; 716 | 717 | /* Provider-level filters */ 718 | enum 719 | { 720 | NSTAT_FILTER_ACCEPT_UNKNOWN = 0x00000001 721 | ,NSTAT_FILTER_ACCEPT_LOOPBACK = 0x00000002 722 | ,NSTAT_FILTER_ACCEPT_CELLULAR = 0x00000004 723 | ,NSTAT_FILTER_ACCEPT_WIFI = 0x00000008 724 | ,NSTAT_FILTER_ACCEPT_WIRED = 0x00000010 725 | ,NSTAT_FILTER_ACCEPT_AWDL = 0x00000020 726 | ,NSTAT_FILTER_ACCEPT_EXPENSIVE = 0x00000040 727 | ,NSTAT_FILTER_ACCEPT_CELLFALLBACK = 0x00000100 728 | ,NSTAT_FILTER_IFNET_FLAGS = 0x00000FFF 729 | 730 | ,NSTAT_FILTER_TCP_NO_LISTENER = 0x00001000 731 | ,NSTAT_FILTER_TCP_ONLY_LISTENER = 0x00002000 732 | ,NSTAT_FILTER_TCP_INTERFACE_ATTACH = 0x00004000 733 | ,NSTAT_FILTER_TCP_NO_EARLY_CLOSE = 0x00008000 734 | ,NSTAT_FILTER_TCP_FLAGS = 0x0000F000 735 | 736 | ,NSTAT_FILTER_UDP_INTERFACE_ATTACH = 0x00010000 737 | ,NSTAT_FILTER_UDP_FLAGS = 0x000F0000 738 | 739 | ,NSTAT_FILTER_SUPPRESS_SRC_ADDED = 0x00100000 740 | ,NSTAT_FILTER_REQUIRE_SRC_ADDED = 0x00200000 741 | ,NSTAT_FILTER_PROVIDER_NOZEROBYTES = 0x00400000 742 | 743 | ,NSTAT_FILTER_SPECIFIC_USER_BY_PID = 0x01000000 744 | ,NSTAT_FILTER_SPECIFIC_USER_BY_EPID = 0x02000000 745 | ,NSTAT_FILTER_SPECIFIC_USER_BY_UUID = 0x04000000 746 | ,NSTAT_FILTER_SPECIFIC_USER_BY_EUUID = 0x08000000 747 | ,NSTAT_FILTER_SPECIFIC_USER = 0x0F000000 748 | }; 749 | 750 | enum 751 | { 752 | NSTAT_MSG_HDR_FLAG_SUPPORTS_AGGREGATE = 1 << 0, 753 | NSTAT_MSG_HDR_FLAG_CONTINUATION = 1 << 1, 754 | NSTAT_MSG_HDR_FLAG_CLOSING = 1 << 2, 755 | }; 756 | 757 | /* 758 | typedef struct nstat_msg_hdr 759 | { 760 | u_int64_t context __attribute__((aligned(sizeof(u_int64_t)))); 761 | u_int32_t type; 762 | u_int16_t length; 763 | u_int16_t flags; 764 | } nstat_msg_hdr; 765 | */ 766 | 767 | typedef struct nstat_msg_error 768 | { 769 | nstat_msg_hdr hdr; 770 | u_int32_t error; // errno error 771 | u_int8_t reserved[4]; 772 | } nstat_msg_error; 773 | 774 | #define NSTAT_ADD_SRC_FIELDS \ 775 | nstat_msg_hdr hdr; \ 776 | nstat_provider_id_t provider; \ 777 | u_int8_t reserved[4] \ 778 | 779 | typedef struct nstat_msg_add_src 780 | { 781 | NSTAT_ADD_SRC_FIELDS; 782 | u_int8_t param[]; 783 | } nstat_msg_add_src_req; 784 | 785 | typedef struct nstat_msg_add_src_header 786 | { 787 | NSTAT_ADD_SRC_FIELDS; 788 | } nstat_msg_add_src_header; 789 | 790 | typedef struct nstat_msg_add_src_convenient 791 | { 792 | nstat_msg_add_src_header hdr; 793 | union { 794 | nstat_route_add_param route; 795 | nstat_tcp_add_param tcp; 796 | nstat_udp_add_param udp; 797 | nstat_ifnet_add_param ifnet; 798 | nstat_sysinfo_add_param sysinfo; 799 | }; 800 | } nstat_msg_add_src_convenient; 801 | 802 | #undef NSTAT_ADD_SRC_FIELDS 803 | 804 | typedef struct nstat_msg_add_all_srcs 805 | { 806 | nstat_msg_hdr hdr; 807 | u_int64_t filter __attribute__((aligned(sizeof(u_int64_t)))); 808 | nstat_event_flags_t events __attribute__((aligned(sizeof(u_int64_t)))); 809 | nstat_provider_id_t provider; 810 | pid_t target_pid; 811 | uuid_t target_uuid; 812 | } nstat_msg_add_all_srcs; 813 | 814 | typedef struct nstat_msg_src_added 815 | { 816 | nstat_msg_hdr hdr; 817 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 818 | nstat_provider_id_t provider; 819 | u_int8_t reserved[4]; 820 | } nstat_msg_src_added; 821 | 822 | typedef struct nstat_msg_rem_src 823 | { 824 | nstat_msg_hdr hdr; 825 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 826 | } nstat_msg_rem_src_req; 827 | 828 | typedef struct nstat_msg_get_src_description 829 | { 830 | nstat_msg_hdr hdr; 831 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 832 | } nstat_msg_get_src_description; 833 | 834 | typedef struct nstat_msg_set_filter 835 | { 836 | nstat_msg_hdr hdr; 837 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 838 | u_int32_t filter; 839 | u_int8_t reserved[4]; 840 | } nstat_msg_set_filter; 841 | 842 | #define NSTAT_SRC_DESCRIPTION_FIELDS \ 843 | nstat_msg_hdr hdr; \ 844 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); \ 845 | nstat_event_flags_t event_flags __attribute__((aligned(sizeof(u_int64_t)))); \ 846 | nstat_provider_id_t provider; \ 847 | u_int8_t reserved[4] 848 | 849 | typedef struct nstat_msg_src_description 850 | { 851 | NSTAT_SRC_DESCRIPTION_FIELDS; 852 | u_int8_t data[]; 853 | } nstat_msg_src_description; 854 | 855 | typedef struct nstat_msg_src_description_header 856 | { 857 | NSTAT_SRC_DESCRIPTION_FIELDS; 858 | } nstat_msg_src_description_header; 859 | 860 | typedef struct nstat_msg_src_description_convenient 861 | { 862 | nstat_msg_src_description_header hdr; 863 | union { 864 | nstat_tcp_descriptor tcp; 865 | nstat_udp_descriptor udp; 866 | nstat_route_descriptor route; 867 | nstat_ifnet_descriptor ifnet; 868 | nstat_sysinfo_descriptor sysinfo; 869 | }; 870 | } nstat_msg_src_description_convenient; 871 | 872 | #undef NSTAT_SRC_DESCRIPTION_FIELDS 873 | 874 | typedef struct nstat_msg_query_src 875 | { 876 | nstat_msg_hdr hdr; 877 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 878 | } nstat_msg_query_src_req; 879 | 880 | typedef struct nstat_msg_src_counts 881 | { 882 | nstat_msg_hdr hdr; 883 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 884 | nstat_event_flags_t event_flags __attribute__((aligned(sizeof(u_int64_t)))); 885 | nstat_counts counts; 886 | } nstat_msg_src_counts; 887 | 888 | #define NSTAT_SRC_UPDATE_FIELDS \ 889 | nstat_msg_hdr hdr; \ 890 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); \ 891 | nstat_event_flags_t event_flags __attribute__((aligned(sizeof(u_int64_t)))); \ 892 | nstat_counts counts; \ 893 | nstat_provider_id_t provider; \ 894 | u_int8_t reserved[4] 895 | 896 | typedef struct nstat_msg_src_update 897 | { 898 | NSTAT_SRC_UPDATE_FIELDS; 899 | u_int8_t data[]; 900 | } nstat_msg_src_update; 901 | 902 | typedef struct nstat_msg_src_update_hdr 903 | { 904 | NSTAT_SRC_UPDATE_FIELDS; 905 | } nstat_msg_src_update_hdr; 906 | 907 | typedef struct nstat_msg_src_update_convenient 908 | { 909 | nstat_msg_src_update_hdr hdr; 910 | union { 911 | nstat_tcp_descriptor tcp; 912 | nstat_udp_descriptor udp; 913 | nstat_route_descriptor route; 914 | nstat_ifnet_descriptor ifnet; 915 | nstat_sysinfo_descriptor sysinfo; 916 | }; 917 | } nstat_msg_src_update_convenient; 918 | 919 | #undef NSTAT_SRC_UPDATE_FIELDS 920 | 921 | typedef struct nstat_msg_src_removed 922 | { 923 | nstat_msg_hdr hdr; 924 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 925 | } nstat_msg_src_removed; 926 | 927 | typedef struct nstat_msg_sysinfo_counts 928 | { 929 | nstat_msg_hdr hdr; 930 | nstat_src_ref_t srcref __attribute__((aligned(sizeof(u_int64_t)))); 931 | nstat_sysinfo_counts counts; 932 | } nstat_msg_sysinfo_counts; 933 | --------------------------------------------------------------------------------