
- Inet diag allows users to gather low-level socket information. - This library provides a higher-level API for creating inetdiag requests (via idiagnl_connect and idiagnl_send_simple) and parsing the replies (via idiagnl_msg_parse). A cache is also provided (via idiagnl_msg_alloc_cache). - Request and message objects provide APIs for accessing and setting the various properties of each. - This library also allows the user to parse the inetdiag response attributes which contain information about traffic class, TOS, congestion, socket memory info, and more depending on the kernel version used. - Includes doxygen documentation.
274 lines
7.1 KiB
C
274 lines
7.1 KiB
C
/*
|
|
* lib/idiag/idiag.c Inet Diag Netlink
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation version 2.1
|
|
* of the License.
|
|
*
|
|
* Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
|
|
*/
|
|
|
|
/**
|
|
* @defgroup idiag Inet Diag library (libnl-idiag)
|
|
* @brief
|
|
* @{
|
|
*/
|
|
|
|
#include <netlink-private/netlink.h>
|
|
#include <netlink/netlink.h>
|
|
#include <netlink/cache.h>
|
|
#include <netlink/idiag/idiagnl.h>
|
|
#include <linux/inet_diag.h>
|
|
|
|
/**
|
|
* @name Socket Creation
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Create and connect idiag netlink socket.
|
|
* @arg sk Netlink socket.
|
|
*
|
|
* Creates a NETLINK_INET_DIAG socket, binds the socket, and issues a connection
|
|
* attemp.
|
|
*
|
|
* @see nl_connect()
|
|
*
|
|
* @return 0 on success or a negative error code.
|
|
*/
|
|
int idiagnl_connect(struct nl_sock *sk)
|
|
{
|
|
return nl_connect(sk, NETLINK_INET_DIAG);
|
|
}
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @name Sending
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Send trivial idiag netlink message
|
|
* @arg sk Netlink socket.
|
|
* @arg flags Message flags
|
|
* @arg family Address family
|
|
* @arg states Socket states to query
|
|
* @arg ext Inet Diag attribute extensions to query
|
|
*
|
|
* @return Newly allocated netlink message or NULL.
|
|
*/
|
|
int idiagnl_send_simple(struct nl_sock *sk, int flags, uint8_t family,
|
|
uint16_t states, uint16_t ext)
|
|
{
|
|
struct inet_diag_req req;
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
flags |= NLM_F_ROOT;
|
|
|
|
req.idiag_family = family;
|
|
req.idiag_states = states;
|
|
req.idiag_ext = ext;
|
|
|
|
return nl_send_simple(sk, TCPDIAG_GETSOCK, flags, &req, sizeof(req));
|
|
}
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @name Inet Diag flag and attribute conversions
|
|
* @{
|
|
*/
|
|
|
|
static const struct trans_tbl idiag_states[] = {
|
|
__ADD(IDIAG_SS_UNKNOWN, unknown)
|
|
__ADD(IDIAG_SS_ESTABLISHED, established)
|
|
__ADD(IDIAG_SS_SYN_SENT, syn_sent)
|
|
__ADD(IDIAG_SS_SYN_RECV, syn_recv)
|
|
__ADD(IDIAG_SS_FIN_WAIT1, fin_wait)
|
|
__ADD(IDIAG_SS_FIN_WAIT2, fin_wait2)
|
|
__ADD(IDIAG_SS_TIME_WAIT, time_wait)
|
|
__ADD(IDIAG_SS_CLOSE, close)
|
|
__ADD(IDIAG_SS_CLOSE_WAIT, close_wait)
|
|
__ADD(IDIAG_SS_LAST_ACK, last_ack)
|
|
__ADD(IDIAG_SS_LISTEN, listen)
|
|
__ADD(IDIAG_SS_CLOSING, closing)
|
|
__ADD(IDIAG_SS_MAX, max)
|
|
{ ((1<<IDIAG_SS_MAX)-1), "all" }
|
|
};
|
|
|
|
/**
|
|
* Convert inet diag socket states to strings.
|
|
* @arg state inetdiag socket state (e.g., IDIAG_SS_ESTABLISHED)
|
|
* @arg buf output buffer which will hold string result
|
|
* @arg len length in bytes of the output buffer
|
|
*
|
|
* @return string representation of the inetdiag socket state or an empty
|
|
* string.
|
|
*/
|
|
char * idiagnl_state2str(int state, char *buf, size_t len)
|
|
{
|
|
return __type2str(state, buf, len, idiag_states,
|
|
ARRAY_SIZE(idiag_states));
|
|
}
|
|
|
|
/**
|
|
* Convert inet diag socket state string to int.
|
|
* @arg name inetdiag socket state string
|
|
*
|
|
* @return the int representation of the socket state strign or a negative error
|
|
* code.
|
|
*/
|
|
int idiagnl_str2state(const char *name)
|
|
{
|
|
return __str2type(name, idiag_states, ARRAY_SIZE(idiag_states));
|
|
}
|
|
|
|
static const struct trans_tbl idiag_timers[] = {
|
|
__ADD(IDIAG_TIMER_OFF, off)
|
|
__ADD(IDIAG_TIMER_ON, on)
|
|
__ADD(IDIAG_TIMER_KEEPALIVE, keepalive)
|
|
__ADD(IDIAG_TIMER_TIMEWAIT, timewait)
|
|
__ADD(IDIAG_TIMER_PERSIST, persist)
|
|
__ADD(IDIAG_TIMER_UNKNOWN, unknown)
|
|
};
|
|
|
|
/**
|
|
* Convert inet diag timer types to strings.
|
|
* @arg timer inetdiag timer (e.g., IDIAG_TIMER_ON)
|
|
* @arg buf output buffer which will hold string result
|
|
* @arg len length in bytes of the output buffer
|
|
*
|
|
* @return string representation of the inetdiag timer type or an empty string.
|
|
*/
|
|
char * idiagnl_timer2str(int timer, char *buf, size_t len)
|
|
{
|
|
return __type2str(timer, buf, len, idiag_timers,
|
|
ARRAY_SIZE(idiag_timers));
|
|
}
|
|
|
|
/**
|
|
* Convert inet diag timer string to int.
|
|
* @arg name inetdiag timer string
|
|
*
|
|
* @return the int representation of the timer string or a negative error code.
|
|
*/
|
|
int idiagnl_str2timer(const char *name)
|
|
{
|
|
return __str2type(name, idiag_timers, ARRAY_SIZE(idiag_timers));
|
|
}
|
|
|
|
static const struct trans_tbl idiag_attrs[] = {
|
|
__ADD(IDIAG_ATTR_NONE, none)
|
|
__ADD(IDIAG_ATTR_MEMINFO, meminfo)
|
|
__ADD(IDIAG_ATTR_INFO, info)
|
|
__ADD(IDIAG_ATTR_VEGASINFO, vegasinfo)
|
|
__ADD(IDIAG_ATTR_CONG, congestion)
|
|
__ADD(IDIAG_ATTR_TOS, tos)
|
|
__ADD(IDIAG_ATTR_TCLASS, tclass)
|
|
};
|
|
|
|
/**
|
|
* Convert inetdiag extended attributes to strings.
|
|
* @arg attrs inetdiag attribute (e.g., IDIAG_ATTR_MEMINFO)
|
|
* @arg buf output buffer which will hold string result
|
|
* @arg len length in bytes of the output buffer
|
|
*
|
|
* @return string representation of attrs or an empty string.
|
|
*/
|
|
char *idiagnl_attrs2str(int attrs, char *buf, size_t len)
|
|
{
|
|
return __type2str(attrs, buf, len, idiag_attrs, ARRAY_SIZE(idiag_attrs));
|
|
}
|
|
|
|
static const struct trans_tbl idiagnl_tcpstates[] = {
|
|
__ADD(TCP_CA_Open, open)
|
|
__ADD(TCP_CA_Disorder, disorder)
|
|
__ADD(TCP_CA_CWR, cwr)
|
|
__ADD(TCP_CA_Recovery, recovery)
|
|
__ADD(TCP_CA_Loss, loss)
|
|
};
|
|
|
|
/**
|
|
* Convert inetdiag tcp states to strings.
|
|
* @arg state TCP state (e.g., TCP_CA_Open)
|
|
* @arg buf output buffer which will hold string result
|
|
* @arg len length in bytes of the output buffer
|
|
*/
|
|
char *idiagnl_tcpstate2str(uint8_t state, char *buf, size_t len)
|
|
{
|
|
return __type2str(state, buf, len, idiagnl_tcpstates,
|
|
ARRAY_SIZE(idiagnl_tcpstates));
|
|
}
|
|
|
|
static const struct trans_tbl idiagnl_tcpopt_attrs[] = {
|
|
__ADD(TCPI_OPT_TIMESTAMPS, timestamps)
|
|
__ADD(TCPI_OPT_SACK, sACK)
|
|
__ADD(TCPI_OPT_WSCALE, wscale)
|
|
__ADD(TCPI_OPT_ECN, ecn)
|
|
};
|
|
|
|
/**
|
|
* Convert TCP option attributes to string
|
|
* @arg attrs TCP option attributes to convert (e.g., TCPI_OPT_SACK |
|
|
* TCPI_OPT_WSCALE)
|
|
* @arg buf Output buffer for string
|
|
* @arg len Length in bytes of output buffer
|
|
*
|
|
* @return buffer with string representation or empty string
|
|
*/
|
|
char *idiagnl_tcpopts2str(uint8_t attrs, char *buf, size_t len)
|
|
{
|
|
return __flags2str(attrs, buf, len, idiagnl_tcpopt_attrs,
|
|
ARRAY_SIZE(idiagnl_tcpopt_attrs));
|
|
}
|
|
|
|
/**
|
|
* Convert shutdown state to string.
|
|
* @arg shutdown Shutdown state (e.g., idiag_msg->shutdown)
|
|
* @arg buf Ouput buffer to hold string representation
|
|
* @arg len Length in bytes of output buffer
|
|
*
|
|
* @return string representation of shutdown state or NULL
|
|
*/
|
|
char * idiagnl_shutdown2str(uint8_t shutdown, char *buf, size_t len)
|
|
{
|
|
if (shutdown == 0) {
|
|
snprintf(buf, len, " ");
|
|
return buf;
|
|
} else if (shutdown == 1) {
|
|
snprintf(buf, len, "receive shutdown");
|
|
return buf;
|
|
} else if (shutdown == 2) {
|
|
snprintf(buf, len, "send shutdown");
|
|
return buf;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const struct trans_tbl idiag_exts[] = {
|
|
__ADD(IDIAG_ATTR_NONE, none)
|
|
__ADD(IDIAG_ATTR_MEMINFO, meminfo)
|
|
__ADD(IDIAG_ATTR_INFO, info)
|
|
__ADD(IDIAG_ATTR_VEGASINFO, vegasinfo)
|
|
__ADD(IDIAG_ATTR_CONG, congestion)
|
|
__ADD(IDIAG_ATTR_TOS, tos)
|
|
__ADD(IDIAG_ATTR_TCLASS, tclass)
|
|
};
|
|
|
|
/**
|
|
* Convert inet diag extension flags to a string.
|
|
* @arg attrs inet diag extension flags (e.g., (IDIAG_ATTR_MEMINFO |
|
|
* IDIAG_ATTR_CONG | IDIAG_ATTR_TOS))
|
|
* @arg buf Output buffer to hold string representation
|
|
* @arg len length in bytes of the output buffer
|
|
*/
|
|
char *idiagnl_exts2str(uint8_t attrs, char *buf, size_t len)
|
|
{
|
|
return __flags2str(attrs, buf, len, idiag_exts, ARRAY_SIZE(idiag_exts));
|
|
}
|
|
|
|
/** @} */
|
|
/** @} */
|