• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
idiagnl_connect(struct nl_sock * sk)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  */
idiagnl_send_simple(struct nl_sock * sk,int flags,uint8_t family,uint16_t states,uint16_t ext)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  */
idiagnl_state2str(int state,char * buf,size_t len)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  */
idiagnl_str2state(const char * name)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  */
idiagnl_timer2str(int timer,char * buf,size_t len)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  */
idiagnl_str2timer(const char * name)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  */
idiagnl_attrs2str(int attrs,char * buf,size_t len)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  */
idiagnl_tcpstate2str(uint8_t state,char * buf,size_t len)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  */
idiagnl_tcpopts2str(uint8_t attrs,char * buf,size_t len)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  */
idiagnl_shutdown2str(uint8_t shutdown,char * buf,size_t len)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  */
idiagnl_exts2str(uint8_t attrs,char * buf,size_t len)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 /** @} */
275