Home | History | Annotate | Download | only in idiag
      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 (at) 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 /** @} */
    275