]>
Commit | Line | Data |
---|---|---|
9dc66a05 A |
1 | /* |
2 | * Copyright (c) 2013 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | ||
29 | #ifdef __APPLE__ | |
30 | #include <TargetConditionals.h> | |
31 | #endif | |
32 | ||
9dc66a05 A |
33 | #include <stdio.h> |
34 | #include <err.h> | |
35 | #include <stdlib.h> | |
36 | #include <strings.h> | |
89c4ed63 | 37 | #include <inttypes.h> |
9dc66a05 A |
38 | |
39 | #include <sys/errno.h> | |
40 | #include <sys/types.h> | |
41 | #include <sys/sysctl.h> | |
42 | ||
43 | #include <netinet/in.h> | |
44 | #include <netinet/tcp.h> | |
45 | #include <netinet/mptcp_var.h> | |
46 | ||
47 | #include <arpa/inet.h> | |
48 | ||
49 | #include "netstat.h" | |
50 | ||
51 | /* XXX we can't include tcp_fsm.h because inet.c already includes it. */ | |
52 | static const char *tcpstates[] = { | |
53 | "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", | |
54 | "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", | |
55 | "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT" | |
56 | }; | |
57 | ||
58 | static const char *mptcpstates[] = { | |
59 | "CLOSED", "LISTEN", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", | |
60 | "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", "FASTCLOSE_WAIT" | |
61 | }; | |
62 | ||
63 | int mptcp_done = 0; | |
64 | extern void inetprint (struct in_addr *, int, char *, int); | |
65 | extern void inet6print (struct in6_addr *, int, char *, int); | |
66 | ||
67 | static void | |
68 | printmptcp(int id, conninfo_mptcp_t *mptcp) | |
69 | { | |
70 | int i; | |
71 | conninfo_tcp_t *tcpci; | |
72 | struct sockaddr_storage *src, *dst; | |
73 | mptcp_flow_t *flow; | |
74 | int af; | |
75 | ||
89c4ed63 A |
76 | printf("mptcp/%-2.2d %-8.8x/%-8.8x %50s \n" |
77 | " [tok(%#"PRIx32") snd(%#"PRIx64") rcv(%#"PRIx64") " | |
78 | "aid(%d)]\n", id, | |
79 | mptcp->mptcpci_mpte_flags, mptcp->mptcpci_flags, | |
80 | mptcpstates[mptcp->mptcpci_state], mptcp->mptcpci_rtoken, | |
81 | mptcp->mptcpci_sndnxt, mptcp->mptcpci_rcvatmark, | |
82 | mptcp->mptcpci_mpte_addrid); | |
83 | ||
84 | flow = (mptcp_flow_t*)((caddr_t)mptcp + mptcp->mptcpci_flow_offset); | |
85 | ||
9dc66a05 | 86 | for (i = 0; i < mptcp->mptcpci_nflows; i++) { |
9dc66a05 A |
87 | src = &flow->flow_src; |
88 | dst = &flow->flow_dst; | |
89 | af = src->ss_family; | |
90 | printf(" tcp%d/%-2.2d ", af == AF_INET ? 4 : 6, | |
91 | flow->flow_cid); | |
92 | printf("%-8.8x ", flow->flow_flags); | |
93 | #define SIN(x) ((struct sockaddr_in *)(x)) | |
94 | #define SIN6(x) ((struct sockaddr_in6 *)(x)) | |
95 | switch (af) { | |
96 | case AF_INET: | |
97 | inetprint(&SIN(src)->sin_addr, SIN(src)->sin_port, | |
98 | "tcp", nflag); | |
99 | inetprint(&SIN(dst)->sin_addr, SIN(dst)->sin_port, | |
100 | "tcp", nflag); | |
101 | break; | |
102 | #ifdef INET6 | |
103 | case AF_INET6: | |
104 | inet6print(&SIN6(src)->sin6_addr, SIN6(src)->sin6_port, | |
105 | "tcp", nflag); | |
106 | inet6print(&SIN6(dst)->sin6_addr, SIN6(dst)->sin6_port, | |
107 | "tcp", nflag); | |
108 | break; | |
109 | } | |
110 | #endif | |
111 | #undef SIN | |
112 | #undef SIN6 | |
89c4ed63 A |
113 | tcpci = (conninfo_tcp_t*)((caddr_t)flow + |
114 | flow->flow_tcpci_offset); | |
115 | printf("%s \n" | |
116 | " [dsn(%#"PRIx64"), relseq(%-4.4d), err(%d)]\n", | |
117 | tcpstates[tcpci->tcpci_tcp_info.tcpi_state], | |
118 | flow->flow_sndnxt, | |
119 | flow->flow_relseq, | |
120 | flow->flow_soerror); | |
121 | ||
122 | flow = (mptcp_flow_t*)((caddr_t)flow + flow->flow_len); | |
9dc66a05 A |
123 | } |
124 | } | |
125 | ||
126 | void | |
127 | mptcppr(uint32_t off, char *name, int af) | |
128 | { | |
129 | #pragma unused(off, name, af) | |
130 | const char *mibvar = "net.inet.mptcp.pcblist"; | |
131 | size_t len = 0; | |
132 | conninfo_mptcp_t *mptcp; | |
133 | char *buf, *bufp; | |
134 | int id = 0; | |
135 | ||
136 | if (Lflag || Aflag || mptcp_done) | |
137 | return; | |
138 | mptcp_done = 1; | |
139 | ||
140 | if (sysctlbyname(mibvar, 0, &len, NULL, 0) < 0) { | |
141 | if (errno != ENOENT) | |
142 | warn("sysctl: %s", mibvar); | |
143 | return; | |
144 | } | |
145 | if ((buf = malloc(len)) == NULL) { | |
146 | warn("malloc"); | |
147 | return; | |
148 | } | |
149 | if (sysctlbyname(mibvar, buf, &len, NULL, 0) < 0) { | |
150 | warn("sysctl: %s", mibvar); | |
151 | free(buf); | |
152 | return; | |
153 | } | |
154 | ||
155 | printf("Active Multipath Internet connections\n"); | |
156 | printf("%-8.8s %-9.9s %-22.22s %-22.22s %-11.11s\n", | |
157 | "Proto/ID", "Flags", | |
158 | "Local Address", "Foreign Address", | |
159 | "(state)"); | |
160 | ||
161 | bufp = buf; | |
162 | while (bufp < buf + len) { | |
163 | /* Sanity check */ | |
164 | if (buf + len - bufp < sizeof(conninfo_mptcp_t)) | |
165 | break; | |
166 | mptcp = (conninfo_mptcp_t *)bufp; | |
167 | printmptcp(id++, mptcp); | |
168 | bufp += mptcp->mptcpci_len; | |
169 | } | |
170 | free(buf); | |
171 | } |