libnl  3.2.24-rc1
idiag.c
1 /*
2  * lib/idiag/idiag.c Inet Diag Netlink
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
10  */
11 
12 /**
13  * @defgroup idiag Inet Diag library (libnl-idiag)
14  * @brief
15  * @{
16  */
17 
18 #include <netlink-private/netlink.h>
19 #include <netlink/netlink.h>
20 #include <netlink/cache.h>
21 #include <netlink/idiag/idiagnl.h>
22 #include <linux/inet_diag.h>
23 
24 /**
25  * @name Socket Creation
26  * @{
27  */
28 
29 /**
30  * Create and connect idiag netlink socket.
31  * @arg sk Netlink socket.
32  *
33  * Creates a NETLINK_INET_DIAG socket, binds the socket, and issues a connection
34  * attemp.
35  *
36  * @see nl_connect()
37  *
38  * @return 0 on success or a negative error code.
39  */
40 int idiagnl_connect(struct nl_sock *sk)
41 {
42  return nl_connect(sk, NETLINK_INET_DIAG);
43 }
44 
45 /** @} */
46 
47 /**
48  * @name Sending
49  * @{
50  */
51 
52 /**
53  * Send trivial idiag netlink message
54  * @arg sk Netlink socket.
55  * @arg flags Message flags
56  * @arg family Address family
57  * @arg states Socket states to query
58  * @arg ext Inet Diag attribute extensions to query
59  *
60  * @return Newly allocated netlink message or NULL.
61  */
62 int idiagnl_send_simple(struct nl_sock *sk, int flags, uint8_t family,
63  uint16_t states, uint16_t ext)
64 {
65  struct inet_diag_req req;
66  memset(&req, 0, sizeof(req));
67 
68  flags |= NLM_F_ROOT;
69 
70  req.idiag_family = family;
71  req.idiag_states = states;
72  req.idiag_ext = ext;
73 
74  return nl_send_simple(sk, TCPDIAG_GETSOCK, flags, &req, sizeof(req));
75 }
76 
77 /** @} */
78 
79 /**
80  * @name Inet Diag flag and attribute conversions
81  * @{
82  */
83 
84 static const struct trans_tbl idiag_states[] = {
85  __ADD(IDIAG_SS_UNKNOWN, unknown)
86  __ADD(IDIAG_SS_ESTABLISHED, established)
87  __ADD(IDIAG_SS_SYN_SENT, syn_sent)
88  __ADD(IDIAG_SS_SYN_RECV, syn_recv)
89  __ADD(IDIAG_SS_FIN_WAIT1, fin_wait)
90  __ADD(IDIAG_SS_FIN_WAIT2, fin_wait2)
91  __ADD(IDIAG_SS_TIME_WAIT, time_wait)
92  __ADD(IDIAG_SS_CLOSE, close)
93  __ADD(IDIAG_SS_CLOSE_WAIT, close_wait)
94  __ADD(IDIAG_SS_LAST_ACK, last_ack)
95  __ADD(IDIAG_SS_LISTEN, listen)
96  __ADD(IDIAG_SS_CLOSING, closing)
97  __ADD(IDIAG_SS_MAX, max)
98  { ((1<<IDIAG_SS_MAX)-1), "all" }
99 };
100 
101 /**
102  * Convert inet diag socket states to strings.
103  * @arg state inetdiag socket state (e.g., IDIAG_SS_ESTABLISHED)
104  * @arg buf output buffer which will hold string result
105  * @arg len length in bytes of the output buffer
106  *
107  * @return string representation of the inetdiag socket state or an empty
108  * string.
109  */
110 char * idiagnl_state2str(int state, char *buf, size_t len)
111 {
112  return __type2str(state, buf, len, idiag_states,
113  ARRAY_SIZE(idiag_states));
114 }
115 
116 /**
117  * Convert inet diag socket state string to int.
118  * @arg name inetdiag socket state string
119  *
120  * @return the int representation of the socket state strign or a negative error
121  * code.
122  */
123 int idiagnl_str2state(const char *name)
124 {
125  return __str2type(name, idiag_states, ARRAY_SIZE(idiag_states));
126 }
127 
128 static const struct trans_tbl idiag_timers[] = {
129  __ADD(IDIAG_TIMER_OFF, off)
130  __ADD(IDIAG_TIMER_ON, on)
131  __ADD(IDIAG_TIMER_KEEPALIVE, keepalive)
132  __ADD(IDIAG_TIMER_TIMEWAIT, timewait)
133  __ADD(IDIAG_TIMER_PERSIST, persist)
134  __ADD(IDIAG_TIMER_UNKNOWN, unknown)
135 };
136 
137 /**
138  * Convert inet diag timer types to strings.
139  * @arg timer inetdiag timer (e.g., IDIAG_TIMER_ON)
140  * @arg buf output buffer which will hold string result
141  * @arg len length in bytes of the output buffer
142  *
143  * @return string representation of the inetdiag timer type or an empty string.
144  */
145 char * idiagnl_timer2str(int timer, char *buf, size_t len)
146 {
147  return __type2str(timer, buf, len, idiag_timers,
148  ARRAY_SIZE(idiag_timers));
149 }
150 
151 /**
152  * Convert inet diag timer string to int.
153  * @arg name inetdiag timer string
154  *
155  * @return the int representation of the timer string or a negative error code.
156  */
157 int idiagnl_str2timer(const char *name)
158 {
159  return __str2type(name, idiag_timers, ARRAY_SIZE(idiag_timers));
160 }
161 
162 static const struct trans_tbl idiag_attrs[] = {
163  __ADD(IDIAG_ATTR_NONE, none)
164  __ADD(IDIAG_ATTR_MEMINFO, meminfo)
165  __ADD(IDIAG_ATTR_INFO, info)
166  __ADD(IDIAG_ATTR_VEGASINFO, vegasinfo)
167  __ADD(IDIAG_ATTR_CONG, congestion)
168  __ADD(IDIAG_ATTR_TOS, tos)
169  __ADD(IDIAG_ATTR_TCLASS, tclass)
170 };
171 
172 /**
173  * Convert inetdiag extended attributes to strings.
174  * @arg attrs inetdiag attribute (e.g., IDIAG_ATTR_MEMINFO)
175  * @arg buf output buffer which will hold string result
176  * @arg len length in bytes of the output buffer
177  *
178  * @return string representation of attrs or an empty string.
179  */
180 char *idiagnl_attrs2str(int attrs, char *buf, size_t len)
181 {
182  return __type2str(attrs, buf, len, idiag_attrs, ARRAY_SIZE(idiag_attrs));
183 }
184 
185 static const struct trans_tbl idiagnl_tcpstates[] = {
186  __ADD(TCP_CA_Open, open)
187  __ADD(TCP_CA_Disorder, disorder)
188  __ADD(TCP_CA_CWR, cwr)
189  __ADD(TCP_CA_Recovery, recovery)
190  __ADD(TCP_CA_Loss, loss)
191 };
192 
193 /**
194  * Convert inetdiag tcp states to strings.
195  * @arg state TCP state (e.g., TCP_CA_Open)
196  * @arg buf output buffer which will hold string result
197  * @arg len length in bytes of the output buffer
198  */
199 char *idiagnl_tcpstate2str(uint8_t state, char *buf, size_t len)
200 {
201  return __type2str(state, buf, len, idiagnl_tcpstates,
202  ARRAY_SIZE(idiagnl_tcpstates));
203 }
204 
205 static const struct trans_tbl idiagnl_tcpopt_attrs[] = {
206  __ADD(TCPI_OPT_TIMESTAMPS, timestamps)
207  __ADD(TCPI_OPT_SACK, sACK)
208  __ADD(TCPI_OPT_WSCALE, wscale)
209  __ADD(TCPI_OPT_ECN, ecn)
210 };
211 
212 /**
213  * Convert TCP option attributes to string
214  * @arg attrs TCP option attributes to convert (e.g., TCPI_OPT_SACK |
215  * TCPI_OPT_WSCALE)
216  * @arg buf Output buffer for string
217  * @arg len Length in bytes of output buffer
218  *
219  * @return buffer with string representation or empty string
220  */
221 char *idiagnl_tcpopts2str(uint8_t attrs, char *buf, size_t len)
222 {
223  return __flags2str(attrs, buf, len, idiagnl_tcpopt_attrs,
224  ARRAY_SIZE(idiagnl_tcpopt_attrs));
225 }
226 
227 /**
228  * Convert shutdown state to string.
229  * @arg shutdown Shutdown state (e.g., idiag_msg->shutdown)
230  * @arg buf Ouput buffer to hold string representation
231  * @arg len Length in bytes of output buffer
232  *
233  * @return string representation of shutdown state or NULL
234  */
235 char * idiagnl_shutdown2str(uint8_t shutdown, char *buf, size_t len)
236 {
237  if (shutdown == 0) {
238  snprintf(buf, len, " ");
239  return buf;
240  } else if (shutdown == 1) {
241  snprintf(buf, len, "receive shutdown");
242  return buf;
243  } else if (shutdown == 2) {
244  snprintf(buf, len, "send shutdown");
245  return buf;
246  }
247 
248  return NULL;
249 }
250 
251 static const struct trans_tbl idiag_exts[] = {
252  __ADD(IDIAG_ATTR_NONE, none)
253  __ADD(IDIAG_ATTR_MEMINFO, meminfo)
254  __ADD(IDIAG_ATTR_INFO, info)
255  __ADD(IDIAG_ATTR_VEGASINFO, vegasinfo)
256  __ADD(IDIAG_ATTR_CONG, congestion)
257  __ADD(IDIAG_ATTR_TOS, tos)
258  __ADD(IDIAG_ATTR_TCLASS, tclass)
259 };
260 
261 /**
262  * Convert inet diag extension flags to a string.
263  * @arg attrs inet diag extension flags (e.g., (IDIAG_ATTR_MEMINFO |
264  * IDIAG_ATTR_CONG | IDIAG_ATTR_TOS))
265  * @arg buf Output buffer to hold string representation
266  * @arg len length in bytes of the output buffer
267  */
268 char *idiagnl_exts2str(uint8_t attrs, char *buf, size_t len)
269 {
270  return __flags2str(attrs, buf, len, idiag_exts, ARRAY_SIZE(idiag_exts));
271 }
272 
273 /** @} */
274 /** @} */