idiag: merge branch 'idiag-fixes'

Deprecate all of the IDIAG_* defines in 'idiagnl.h'.
Names exposed by libnl should have the prefix IDIAGNL_*
instead.

But actually, most of these values were copies from other
system headers. The user should instead use the original defines
anyway.

Also, several fixes of the idiag_msg_obj, which had a broken
oo_clone() function and missing oo_compare().

http://lists.infradead.org/pipermail/libnl/2014-November/001726.html

Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
Thomas Haller 2014-11-24 18:41:39 +01:00
commit 60ad8251f8
9 changed files with 449 additions and 154 deletions

View file

@ -131,6 +131,7 @@ noinst_HEADERS = \
linux-private/linux/if_link.h \
linux-private/linux/if_tunnel.h \
linux-private/linux/if_vlan.h \
linux-private/linux/inet_diag.h \
linux-private/linux/ip.h \
linux-private/linux/ip_mp_alg.h \
linux-private/linux/ipv6.h \

View file

@ -0,0 +1,137 @@
#ifndef _UAPI_INET_DIAG_H_
#define _UAPI_INET_DIAG_H_
#include <linux/types.h>
/* Just some random number */
#define TCPDIAG_GETSOCK 18
#define DCCPDIAG_GETSOCK 19
#define INET_DIAG_GETSOCK_MAX 24
/* Socket identity */
struct inet_diag_sockid {
__be16 idiag_sport;
__be16 idiag_dport;
__be32 idiag_src[4];
__be32 idiag_dst[4];
__u32 idiag_if;
__u32 idiag_cookie[2];
#define INET_DIAG_NOCOOKIE (~0U)
};
/* Request structure */
struct inet_diag_req {
__u8 idiag_family; /* Family of addresses. */
__u8 idiag_src_len;
__u8 idiag_dst_len;
__u8 idiag_ext; /* Query extended information */
struct inet_diag_sockid id;
__u32 idiag_states; /* States to dump */
__u32 idiag_dbs; /* Tables to dump (NI) */
};
struct inet_diag_req_v2 {
__u8 sdiag_family;
__u8 sdiag_protocol;
__u8 idiag_ext;
__u8 pad;
__u32 idiag_states;
struct inet_diag_sockid id;
};
enum {
INET_DIAG_REQ_NONE,
INET_DIAG_REQ_BYTECODE,
};
#define INET_DIAG_REQ_MAX INET_DIAG_REQ_BYTECODE
/* Bytecode is sequence of 4 byte commands followed by variable arguments.
* All the commands identified by "code" are conditional jumps forward:
* to offset cc+"yes" or to offset cc+"no". "yes" is supposed to be
* length of the command and its arguments.
*/
struct inet_diag_bc_op {
unsigned char code;
unsigned char yes;
unsigned short no;
};
enum {
INET_DIAG_BC_NOP,
INET_DIAG_BC_JMP,
INET_DIAG_BC_S_GE,
INET_DIAG_BC_S_LE,
INET_DIAG_BC_D_GE,
INET_DIAG_BC_D_LE,
INET_DIAG_BC_AUTO,
INET_DIAG_BC_S_COND,
INET_DIAG_BC_D_COND,
};
struct inet_diag_hostcond {
__u8 family;
__u8 prefix_len;
int port;
__be32 addr[0];
};
/* Base info structure. It contains socket identity (addrs/ports/cookie)
* and, alas, the information shown by netstat. */
struct inet_diag_msg {
__u8 idiag_family;
__u8 idiag_state;
__u8 idiag_timer;
__u8 idiag_retrans;
struct inet_diag_sockid id;
__u32 idiag_expires;
__u32 idiag_rqueue;
__u32 idiag_wqueue;
__u32 idiag_uid;
__u32 idiag_inode;
};
/* Extensions */
enum {
INET_DIAG_NONE,
INET_DIAG_MEMINFO,
INET_DIAG_INFO,
INET_DIAG_VEGASINFO,
INET_DIAG_CONG,
INET_DIAG_TOS,
INET_DIAG_TCLASS,
INET_DIAG_SKMEMINFO,
INET_DIAG_SHUTDOWN,
};
#define INET_DIAG_MAX INET_DIAG_SHUTDOWN
/* INET_DIAG_MEM */
struct inet_diag_meminfo {
__u32 idiag_rmem;
__u32 idiag_wmem;
__u32 idiag_fmem;
__u32 idiag_tmem;
};
/* INET_DIAG_VEGASINFO */
struct tcpvegas_info {
__u32 tcpv_enabled;
__u32 tcpv_rttcnt;
__u32 tcpv_rtt;
__u32 tcpv_minrtt;
};
#endif /* _UAPI_INET_DIAG_H_ */

View file

@ -19,8 +19,16 @@
extern "C" {
#endif
/*************************************************************
* The following part contains DEPRECATED names and defines.
* Don't use them.
*************************************************************/
/**
* Inet Diag message types
*
* deprecated: use TCPDIAG_GETSOCK, DCCPDIAG_GETSOCK and
* INET_DIAG_GETSOCK_MAX from linux/inet_diag.h
*/
#define IDIAG_TCPDIAG_GETSOCK 18
#define IDIAG_DCCPDIAG_GETSOCK 19
@ -29,53 +37,59 @@ extern "C" {
/**
* Socket state identifiers
* @ingroup idiag
* @deprecated: use instead the TCP_* defines from netinet/tcp.h.
*/
enum {
IDIAG_SS_UNKNOWN,
IDIAG_SS_ESTABLISHED,
IDIAG_SS_SYN_SENT,
IDIAG_SS_SYN_RECV,
IDIAG_SS_FIN_WAIT1,
IDIAG_SS_FIN_WAIT2,
IDIAG_SS_TIME_WAIT,
IDIAG_SS_CLOSE,
IDIAG_SS_CLOSE_WAIT,
IDIAG_SS_LAST_ACK,
IDIAG_SS_LISTEN,
IDIAG_SS_CLOSING,
IDIAG_SS_MAX
IDIAG_SS_UNKNOWN = 0,
IDIAG_SS_ESTABLISHED = 1, /* TCP_ESTABLISHED */
IDIAG_SS_SYN_SENT = 2, /* TCP_SYN_SENT */
IDIAG_SS_SYN_RECV = 3, /* TCP_SYN_RECV */
IDIAG_SS_FIN_WAIT1 = 4, /* TCP_FIN_WAIT1 */
IDIAG_SS_FIN_WAIT2 = 5, /* TCP_FIN_WAIT2 */
IDIAG_SS_TIME_WAIT = 6, /* TCP_TIME_WAIT */
IDIAG_SS_CLOSE = 7, /* TCP_CLOSE */
IDIAG_SS_CLOSE_WAIT = 8, /* TCP_CLOSE_WAIT */
IDIAG_SS_LAST_ACK = 9, /* TCP_LAST_ACK */
IDIAG_SS_LISTEN = 10, /* TCP_LISTEN */
IDIAG_SS_CLOSING = 11, /* TCP_CLOSING */
IDIAG_SS_MAX = 12,
};
/**
* Macro to represent all socket states.
* @ingroup idiag
* @deprecated
*/
#define IDIAG_SS_ALL ((1<<IDIAG_SS_MAX)-1)
#define IDIAG_SS_ALL IDIAGNL_SS_ALL
/**
* Inet Diag extended attributes
* @ingroup idiag
*/
* @deprecated These attributes should not be used. They mirror the
* INET_DIAG_* extension flags from kernel headers. Use those instead. */
enum {
IDIAG_ATTR_NONE,
IDIAG_ATTR_MEMINFO,
IDIAG_ATTR_INFO,
IDIAG_ATTR_VEGASINFO,
IDIAG_ATTR_CONG,
IDIAG_ATTR_TOS,
IDIAG_ATTR_TCLASS,
IDIAG_ATTR_SKMEMINFO,
IDIAG_ATTR_SHUTDOWN,
IDIAG_ATTR_MAX,
IDIAG_ATTR_NONE = 0, /* INET_DIAG_NONE */
IDIAG_ATTR_MEMINFO = 1, /* INET_DIAG_MEMINFO */
IDIAG_ATTR_INFO = 2, /* INET_DIAG_INFO */
IDIAG_ATTR_VEGASINFO = 3, /* INET_DIAG_VEGASINFO */
IDIAG_ATTR_CONG = 4, /* INET_DIAG_CONG */
IDIAG_ATTR_TOS = 5, /* INET_DIAG_TOS */
IDIAG_ATTR_TCLASS = 6, /* INET_DIAG_TCLASS */
IDIAG_ATTR_SKMEMINFO = 7, /* INET_DIAG_SKMEMINFO */
IDIAG_ATTR_SHUTDOWN = 8, /* INET_DIAG_SHUTDOWN */
/* IDIAG_ATTR_MAX was wrong, because it did not correspond to
* INET_DIAG_MAX. Anyway, freeze it to the previous value. */
IDIAG_ATTR_MAX = 9,
IDIAG_ATTR_ALL = (1<<IDIAG_ATTR_MAX) - 1,
};
/**
* Macro to represent all socket attributes.
* @ingroup idiag
*/
#define IDIAG_ATTR_ALL ((1<<IDIAG_ATTR_MAX)-1)
/* Keep these only for compatibility, DO NOT USE THEM */
/* deprectated keep these only for compatibility, DO NOT USE THEM */
#define IDIAG_SK_MEMINFO_RMEM_ALLOC SK_MEMINFO_RMEM_ALLOC
#define IDIAG_SK_MEMINFO_RCVBUF SK_MEMINFO_RCVBUF
#define IDIAG_SK_MEMINFO_WMEM_ALLOC SK_MEMINFO_WMEM_ALLOC
@ -86,17 +100,33 @@ enum {
#define IDIAG_SK_MEMINFO_BACKLOG SK_MEMINFO_BACKLOG
#define IDIAG_SK_MEMINFO_VARS SK_MEMINFO_VARS
/* deprecated names. */
#define IDIAG_TIMER_OFF IDIAGNL_TIMER_OFF
#define IDIAG_TIMER_ON IDIAGNL_TIMER_ON
#define IDIAG_TIMER_KEEPALIVE IDIAGNL_TIMER_KEEPALIVE
#define IDIAG_TIMER_TIMEWAIT IDIAGNL_TIMER_TIMEWAIT
#define IDIAG_TIMER_PERSIST IDIAGNL_TIMER_PERSIST
#define IDIAG_TIMER_UNKNOWN IDIAGNL_TIMER_UNKNOWN
/*************************************************************/
/**
* Macro to represent all socket states.
* @ingroup idiag
*/
#define IDIAGNL_SS_ALL (((1<<12)-1))
/**
* Socket timer indentifiers
* @ingroupd idiag
*/
enum {
IDIAG_TIMER_OFF,
IDIAG_TIMER_ON,
IDIAG_TIMER_KEEPALIVE,
IDIAG_TIMER_TIMEWAIT,
IDIAG_TIMER_PERSIST,
IDIAG_TIMER_UNKNOWN,
IDIAGNL_TIMER_OFF = 0,
IDIAGNL_TIMER_ON = 1,
IDIAGNL_TIMER_KEEPALIVE = 2,
IDIAGNL_TIMER_TIMEWAIT = 3,
IDIAGNL_TIMER_PERSIST = 4,
IDIAGNL_TIMER_UNKNOWN = 5,
};
extern char * idiagnl_state2str(int, char *, size_t);

View file

@ -19,6 +19,8 @@ extern "C" {
#endif /* __cplusplus */
struct idiagnl_msg;
/* @deprecated: DO NOT USE this variable. */
extern struct nl_object_ops idiagnl_msg_obj_ops;
extern struct idiagnl_msg * idiagnl_msg_alloc(void);

View file

@ -82,25 +82,22 @@ int idiagnl_send_simple(struct nl_sock *sk, int flags, uint8_t family,
*/
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" }
__ADD(TCP_ESTABLISHED, established),
__ADD(TCP_SYN_SENT, syn_sent),
__ADD(TCP_SYN_RECV, syn_recv),
__ADD(TCP_FIN_WAIT1, fin_wait),
__ADD(TCP_FIN_WAIT2, fin_wait2),
__ADD(TCP_TIME_WAIT, time_wait),
__ADD(TCP_CLOSE, close),
__ADD(TCP_CLOSE_WAIT, close_wait),
__ADD(TCP_LAST_ACK, last_ack),
__ADD(TCP_LISTEN, listen),
__ADD(TCP_CLOSING, closing),
};
/**
* Convert inet diag socket states to strings.
* @arg state inetdiag socket state (e.g., IDIAG_SS_ESTABLISHED)
* @arg state inetdiag socket state (e.g., TCP_ESTABLISHED)
* @arg buf output buffer which will hold string result
* @arg len length in bytes of the output buffer
*
@ -126,17 +123,17 @@ int idiagnl_str2state(const char *name)
}
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),
__ADD(IDIAGNL_TIMER_OFF, off),
__ADD(IDIAGNL_TIMER_ON, on),
__ADD(IDIAGNL_TIMER_KEEPALIVE, keepalive),
__ADD(IDIAGNL_TIMER_TIMEWAIT, timewait),
__ADD(IDIAGNL_TIMER_PERSIST, persist),
__ADD(IDIAGNL_TIMER_UNKNOWN, unknown),
};
/**
* Convert inet diag timer types to strings.
* @arg timer inetdiag timer (e.g., IDIAG_TIMER_ON)
* @arg timer inetdiag timer (e.g., IDIAGNL_TIMER_ON)
* @arg buf output buffer which will hold string result
* @arg len length in bytes of the output buffer
*
@ -159,27 +156,41 @@ 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),
static const struct trans_tbl idiag_exts[] = {
__ADD(INET_DIAG_NONE, none),
__ADD(INET_DIAG_MEMINFO, meminfo),
__ADD(INET_DIAG_INFO, info),
__ADD(INET_DIAG_VEGASINFO, vegasinfo),
__ADD(INET_DIAG_CONG, congestion),
__ADD(INET_DIAG_TOS, tos),
__ADD(INET_DIAG_TCLASS, tclass),
};
/**
* Convert inetdiag extended attributes to strings.
* @arg attrs inetdiag attribute (e.g., IDIAG_ATTR_MEMINFO)
* Convert inet diag extension flags to a string.
* @arg attrs inet diag extension flag (e.g., INET_DIAG_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.
* @deprecated This function returns almost the same as idiagnl_exts2str(),
* except that the latter only supports @attrs of uint8_t.
*/
char *idiagnl_attrs2str(int attrs, char *buf, size_t len)
{
return __type2str(attrs, buf, len, idiag_attrs, ARRAY_SIZE(idiag_attrs));
return __flags2str(attrs, buf, len, idiag_exts, ARRAY_SIZE(idiag_exts));
}
/**
* Convert inet diag extension flags to a string.
* @arg attrs inet diag extension flags (e.g., (INET_DIAG_MEMINFO |
* INET_DIAG_CONG | INET_DIAG_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));
}
static const struct trans_tbl idiagnl_tcpstates[] = {
@ -248,27 +259,5 @@ char * idiagnl_shutdown2str(uint8_t shutdown, char *buf, size_t len)
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));
}
/** @} */
/** @} */

View file

@ -80,21 +80,10 @@ void idiagnl_meminfo_set_tmem(struct idiagnl_meminfo *minfo, uint32_t tmem)
}
/** @} */
static int idiagnl_meminfo_clone(struct nl_object *_dst, struct nl_object *_src)
{
struct idiagnl_meminfo *dst = (struct idiagnl_meminfo *) _dst;
struct idiagnl_meminfo *src = (struct idiagnl_meminfo *) _src;
memcpy(dst, src, sizeof(struct idiagnl_meminfo));
return 0;
}
/** @cond SKIP */
struct nl_object_ops idiagnl_meminfo_obj_ops = {
.oo_name = "idiag/idiag_meminfo",
.oo_size = sizeof(struct idiagnl_meminfo),
.oo_clone = idiagnl_meminfo_clone,
};
/** @endcond */
/** @} */

View file

@ -16,6 +16,34 @@
#include <netlink/idiag/vegasinfo.h>
#include <linux/inet_diag.h>
/** @cond SKIP */
#define IDIAGNL_ATTR_FAMILY (0x1 << 1)
#define IDIAGNL_ATTR_STATE (0x1 << 2)
#define IDIAGNL_ATTR_TIMER (0x1 << 3)
#define IDIAGNL_ATTR_RETRANS (0x1 << 4)
#define IDIAGNL_ATTR_SPORT (0x1 << 5)
#define IDIAGNL_ATTR_DPORT (0x1 << 6)
#define IDIAGNL_ATTR_SRC (0x1 << 7)
#define IDIAGNL_ATTR_DST (0x1 << 8)
#define IDIAGNL_ATTR_IFINDEX (0x1 << 9)
#define IDIAGNL_ATTR_EXPIRES (0x1 << 10)
#define IDIAGNL_ATTR_RQUEUE (0x1 << 11)
#define IDIAGNL_ATTR_WQUEUE (0x1 << 12)
#define IDIAGNL_ATTR_UID (0x1 << 13)
#define IDIAGNL_ATTR_INODE (0x1 << 14)
#define IDIAGNL_ATTR_TOS (0x1 << 15)
#define IDIAGNL_ATTR_TCLASS (0x1 << 16)
#define IDIAGNL_ATTR_SHUTDOWN (0x1 << 17)
#define IDIAGNL_ATTR_CONG (0x1 << 18)
#define IDIAGNL_ATTR_MEMINFO (0x1 << 19)
#define IDIAGNL_ATTR_VEGASINFO (0x1 << 20)
#define IDIAGNL_ATTR_TCPINFO (0x1 << 21)
#define IDIAGNL_ATTR_SKMEMINFO (0x1 << 22)
#define _INET_DIAG_ALL ((1<<(INET_DIAG_MAX+1))-1)
/** @endcond */
/**
* @ingroup idiag
* @defgroup idiagnl_msg Inet Diag Messages
@ -61,15 +89,15 @@ static int idiagnl_request_update(struct nl_cache *cache, struct nl_sock *sk)
int family = cache->c_iarg1;
int states = cache->c_iarg2;
return idiagnl_send_simple(sk, 0, family, states, IDIAG_ATTR_ALL);
return idiagnl_send_simple(sk, 0, family, states, _INET_DIAG_ALL);
}
static struct nl_cache_ops idiagnl_msg_ops = {
.co_name = "idiag/idiag",
.co_hdrsize = sizeof(struct inet_diag_msg),
.co_msgtypes = {
{ IDIAG_TCPDIAG_GETSOCK, NL_ACT_NEW, "new" },
{ IDIAG_DCCPDIAG_GETSOCK, NL_ACT_NEW, "new" },
{ TCPDIAG_GETSOCK, NL_ACT_NEW, "new" },
{ DCCPDIAG_GETSOCK, NL_ACT_NEW, "new" },
END_OF_MSGTYPES_LIST,
},
.co_protocol = NETLINK_INET_DIAG,
@ -140,6 +168,7 @@ uint8_t idiagnl_msg_get_family(const struct idiagnl_msg *msg)
void idiagnl_msg_set_family(struct idiagnl_msg *msg, uint8_t family)
{
msg->idiag_family = family;
msg->ce_mask |= IDIAGNL_ATTR_FAMILY;
}
uint8_t idiagnl_msg_get_state(const struct idiagnl_msg *msg)
@ -150,6 +179,7 @@ uint8_t idiagnl_msg_get_state(const struct idiagnl_msg *msg)
void idiagnl_msg_set_state(struct idiagnl_msg *msg, uint8_t state)
{
msg->idiag_state = state;
msg->ce_mask |= IDIAGNL_ATTR_STATE;
}
uint8_t idiagnl_msg_get_timer(const struct idiagnl_msg *msg)
@ -160,6 +190,7 @@ uint8_t idiagnl_msg_get_timer(const struct idiagnl_msg *msg)
void idiagnl_msg_set_timer(struct idiagnl_msg *msg, uint8_t timer)
{
msg->idiag_timer = timer;
msg->ce_mask |= IDIAGNL_ATTR_TIMER;
}
uint8_t idiagnl_msg_get_retrans(const struct idiagnl_msg *msg)
@ -170,6 +201,7 @@ uint8_t idiagnl_msg_get_retrans(const struct idiagnl_msg *msg)
void idiagnl_msg_set_retrans(struct idiagnl_msg *msg, uint8_t retrans)
{
msg->idiag_retrans = retrans;
msg->ce_mask |= IDIAGNL_ATTR_RETRANS;
}
uint16_t idiagnl_msg_get_sport(struct idiagnl_msg *msg)
@ -180,6 +212,7 @@ uint16_t idiagnl_msg_get_sport(struct idiagnl_msg *msg)
void idiagnl_msg_set_sport(struct idiagnl_msg *msg, uint16_t port)
{
msg->idiag_sport = port;
msg->ce_mask |= IDIAGNL_ATTR_SPORT;
}
uint16_t idiagnl_msg_get_dport(struct idiagnl_msg *msg)
@ -190,6 +223,7 @@ uint16_t idiagnl_msg_get_dport(struct idiagnl_msg *msg)
void idiagnl_msg_set_dport(struct idiagnl_msg *msg, uint16_t port)
{
msg->idiag_dport = port;
msg->ce_mask |= IDIAGNL_ATTR_DPORT;
}
struct nl_addr *idiagnl_msg_get_src(const struct idiagnl_msg *msg)
@ -204,6 +238,7 @@ int idiagnl_msg_set_src(struct idiagnl_msg *msg, struct nl_addr *addr)
nl_addr_get(addr);
msg->idiag_src = addr;
msg->ce_mask |= IDIAGNL_ATTR_SRC;
return 0;
}
@ -220,6 +255,7 @@ int idiagnl_msg_set_dst(struct idiagnl_msg *msg, struct nl_addr *addr)
nl_addr_get(addr);
msg->idiag_dst = addr;
msg->ce_mask |= IDIAGNL_ATTR_DST;
return 0;
}
@ -232,6 +268,7 @@ uint32_t idiagnl_msg_get_ifindex(const struct idiagnl_msg *msg)
void idiagnl_msg_set_ifindex(struct idiagnl_msg *msg, uint32_t ifindex)
{
msg->idiag_ifindex = ifindex;
msg->ce_mask |= IDIAGNL_ATTR_IFINDEX;
}
uint32_t idiagnl_msg_get_expires(const struct idiagnl_msg *msg)
@ -242,6 +279,7 @@ uint32_t idiagnl_msg_get_expires(const struct idiagnl_msg *msg)
void idiagnl_msg_set_expires(struct idiagnl_msg *msg, uint32_t expires)
{
msg->idiag_expires = expires;
msg->ce_mask |= IDIAGNL_ATTR_EXPIRES;
}
uint32_t idiagnl_msg_get_rqueue(const struct idiagnl_msg *msg)
@ -252,6 +290,7 @@ uint32_t idiagnl_msg_get_rqueue(const struct idiagnl_msg *msg)
void idiagnl_msg_set_rqueue(struct idiagnl_msg *msg, uint32_t rqueue)
{
msg->idiag_rqueue = rqueue;
msg->ce_mask |= IDIAGNL_ATTR_RQUEUE;
}
uint32_t idiagnl_msg_get_wqueue(const struct idiagnl_msg *msg)
@ -262,6 +301,7 @@ uint32_t idiagnl_msg_get_wqueue(const struct idiagnl_msg *msg)
void idiagnl_msg_set_wqueue(struct idiagnl_msg *msg, uint32_t wqueue)
{
msg->idiag_wqueue = wqueue;
msg->ce_mask |= IDIAGNL_ATTR_WQUEUE;
}
uint32_t idiagnl_msg_get_uid(const struct idiagnl_msg *msg)
@ -272,6 +312,7 @@ uint32_t idiagnl_msg_get_uid(const struct idiagnl_msg *msg)
void idiagnl_msg_set_uid(struct idiagnl_msg *msg, uint32_t uid)
{
msg->idiag_uid = uid;
msg->ce_mask |= IDIAGNL_ATTR_UID;
}
uint32_t idiagnl_msg_get_inode(const struct idiagnl_msg *msg)
@ -282,6 +323,7 @@ uint32_t idiagnl_msg_get_inode(const struct idiagnl_msg *msg)
void idiagnl_msg_set_inode(struct idiagnl_msg *msg, uint32_t inode)
{
msg->idiag_inode = inode;
msg->ce_mask |= IDIAGNL_ATTR_INODE;
}
uint8_t idiagnl_msg_get_tos(const struct idiagnl_msg *msg)
@ -292,6 +334,7 @@ uint8_t idiagnl_msg_get_tos(const struct idiagnl_msg *msg)
void idiagnl_msg_set_tos(struct idiagnl_msg *msg, uint8_t tos)
{
msg->idiag_tos = tos;
msg->ce_mask |= IDIAGNL_ATTR_TOS;
}
uint8_t idiagnl_msg_get_tclass(const struct idiagnl_msg *msg)
@ -302,6 +345,7 @@ uint8_t idiagnl_msg_get_tclass(const struct idiagnl_msg *msg)
void idiagnl_msg_set_tclass(struct idiagnl_msg *msg, uint8_t tclass)
{
msg->idiag_tclass = tclass;
msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
}
uint8_t idiagnl_msg_get_shutdown(const struct idiagnl_msg *msg)
@ -312,6 +356,7 @@ uint8_t idiagnl_msg_get_shutdown(const struct idiagnl_msg *msg)
void idiagnl_msg_set_shutdown(struct idiagnl_msg *msg, uint8_t shutdown)
{
msg->idiag_shutdown = shutdown;
msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
}
char *idiagnl_msg_get_cong(const struct idiagnl_msg *msg)
@ -321,7 +366,9 @@ char *idiagnl_msg_get_cong(const struct idiagnl_msg *msg)
void idiagnl_msg_set_cong(struct idiagnl_msg *msg, char *cong)
{
free (msg->idiag_cong);
msg->idiag_cong = strdup(cong);
msg->ce_mask |= IDIAGNL_ATTR_CONG;
}
struct idiagnl_meminfo *idiagnl_msg_get_meminfo(const struct idiagnl_msg *msg)
@ -329,14 +376,14 @@ struct idiagnl_meminfo *idiagnl_msg_get_meminfo(const struct idiagnl_msg *msg)
return msg->idiag_meminfo;
}
void idiagnl_msg_set_meminfo(struct idiagnl_msg *msg, struct idiagnl_meminfo
*minfo)
void idiagnl_msg_set_meminfo(struct idiagnl_msg *msg, struct idiagnl_meminfo *minfo)
{
if (msg->idiag_meminfo)
idiagnl_meminfo_put(msg->idiag_meminfo);
idiagnl_meminfo_get(minfo);
msg->idiag_meminfo = minfo;
msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
}
struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(const struct idiagnl_msg *msg)
@ -344,14 +391,14 @@ struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(const struct idiagnl_msg *ms
return msg->idiag_vegasinfo;
}
void idiagnl_msg_set_vegasinfo(struct idiagnl_msg *msg, struct idiagnl_vegasinfo
*vinfo)
void idiagnl_msg_set_vegasinfo(struct idiagnl_msg *msg, struct idiagnl_vegasinfo *vinfo)
{
if (msg->idiag_vegasinfo)
idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
idiagnl_vegasinfo_get(vinfo);
msg->idiag_vegasinfo = vinfo;
msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
}
struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
@ -362,6 +409,7 @@ struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
void idiagnl_msg_set_tcpinfo(struct idiagnl_msg *msg, struct tcp_info *tinfo)
{
memcpy(&msg->idiag_tcpinfo, tinfo, sizeof(struct tcp_info));
msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
}
/** @} */
@ -568,27 +616,60 @@ static int idiagnl_msg_clone(struct nl_object *_dst, struct nl_object *_src)
struct idiagnl_msg *dst = (struct idiagnl_msg *) _dst;
struct idiagnl_msg *src = (struct idiagnl_msg *) _src;
if (src->idiag_src)
dst->idiag_cong = NULL;
dst->idiag_src = NULL;
dst->idiag_dst = NULL;
dst->idiag_meminfo = NULL;
dst->idiag_vegasinfo = NULL;
dst->ce_mask &= ~(IDIAGNL_ATTR_CONG |
IDIAGNL_ATTR_SRC |
IDIAGNL_ATTR_DST |
IDIAGNL_ATTR_MEMINFO |
IDIAGNL_ATTR_VEGASINFO);
if (src->idiag_cong) {
if (!(dst->idiag_cong = strdup(src->idiag_cong)))
return -NLE_NOMEM;
dst->ce_mask |= IDIAGNL_ATTR_CONG;
}
if (src->idiag_src) {
if (!(dst->idiag_src = nl_addr_clone(src->idiag_src)))
return -NLE_NOMEM;
dst->ce_mask |= IDIAGNL_ATTR_SRC;
}
if (src->idiag_dst)
if (src->idiag_dst) {
if (!(dst->idiag_dst = nl_addr_clone(src->idiag_dst)))
return -NLE_NOMEM;
dst->ce_mask |= IDIAGNL_ATTR_DST;
}
if (src->idiag_meminfo) {
if (!(dst->idiag_meminfo = (struct idiagnl_meminfo *) nl_object_clone((struct nl_object *) src->idiag_meminfo)))
return -NLE_NOMEM;
dst->ce_mask |= IDIAGNL_ATTR_MEMINFO;
}
if (src->idiag_vegasinfo) {
if (!(dst->idiag_vegasinfo = (struct idiagnl_vegasinfo *) nl_object_clone((struct nl_object *) src->idiag_vegasinfo)))
return -NLE_NOMEM;
dst->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
}
return 0;
}
static struct nla_policy ext_policy[IDIAG_ATTR_MAX] = {
[IDIAG_ATTR_MEMINFO] = { .minlen = sizeof(struct inet_diag_meminfo) },
[IDIAG_ATTR_INFO] = { .minlen = sizeof(struct tcp_info) },
[IDIAG_ATTR_VEGASINFO] = { .minlen = sizeof(struct tcpvegas_info) },
[IDIAG_ATTR_CONG] = { .type = NLA_STRING },
[IDIAG_ATTR_TOS] = { .type = NLA_U8 },
[IDIAG_ATTR_TCLASS] = { .type = NLA_U8 },
static struct nla_policy ext_policy[INET_DIAG_MAX+1] = {
[INET_DIAG_MEMINFO] = { .minlen = sizeof(struct inet_diag_meminfo) },
[INET_DIAG_INFO] = { .minlen = sizeof(struct tcp_info) },
[INET_DIAG_VEGASINFO] = { .minlen = sizeof(struct tcpvegas_info) },
[INET_DIAG_CONG] = { .type = NLA_STRING },
[INET_DIAG_TOS] = { .type = NLA_U8 },
[INET_DIAG_TCLASS] = { .type = NLA_U8 },
/* Older kernel doesn't have SK_MEMINFO_BACKLOG */
[IDIAG_ATTR_SKMEMINFO] = { .minlen = (sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) },
[IDIAG_ATTR_SHUTDOWN] = { .type = NLA_U8 },
[INET_DIAG_SKMEMINFO] = { .minlen = (sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) },
[INET_DIAG_SHUTDOWN] = { .type = NLA_U8 },
};
int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
@ -596,14 +677,14 @@ int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
struct idiagnl_msg *msg = NULL;
struct inet_diag_msg *raw_msg = NULL;
struct nl_addr *src = NULL, *dst = NULL;
struct nlattr *tb[IDIAG_ATTR_MAX];
struct nlattr *tb[INET_DIAG_MAX+1];
int err = 0;
msg = idiagnl_msg_alloc();
if (!msg)
goto errout_nomem;
err = nlmsg_parse(nlh, sizeof(struct inet_diag_msg), tb, IDIAG_ATTR_MAX,
err = nlmsg_parse(nlh, sizeof(struct inet_diag_msg), tb, INET_DIAG_MAX,
ext_policy);
if (err < 0)
goto errout;
@ -622,6 +703,19 @@ int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
msg->idiag_dport = raw_msg->id.idiag_dport;
msg->idiag_ifindex = raw_msg->id.idiag_if;
msg->ce_mask = (IDIAGNL_ATTR_FAMILY |
IDIAGNL_ATTR_STATE |
IDIAGNL_ATTR_TIMER |
IDIAGNL_ATTR_RETRANS |
IDIAGNL_ATTR_EXPIRES |
IDIAGNL_ATTR_RQUEUE |
IDIAGNL_ATTR_WQUEUE |
IDIAGNL_ATTR_UID |
IDIAGNL_ATTR_INODE |
IDIAGNL_ATTR_SPORT |
IDIAGNL_ATTR_DPORT |
IDIAGNL_ATTR_IFINDEX);
dst = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
sizeof(raw_msg->id.idiag_dst));
if (!dst)
@ -644,23 +738,33 @@ int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
nl_addr_put(src);
if (tb[IDIAG_ATTR_TOS])
msg->idiag_tos = nla_get_u8(tb[IDIAG_ATTR_TOS]);
if (tb[INET_DIAG_TOS]) {
msg->idiag_tos = nla_get_u8(tb[INET_DIAG_TOS]);
msg->ce_mask |= IDIAGNL_ATTR_TOS;
}
if (tb[IDIAG_ATTR_TCLASS])
msg->idiag_tclass = nla_get_u8(tb[IDIAG_ATTR_TCLASS]);
if (tb[INET_DIAG_TCLASS]) {
msg->idiag_tclass = nla_get_u8(tb[INET_DIAG_TCLASS]);
msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
}
if (tb[IDIAG_ATTR_SHUTDOWN])
msg->idiag_shutdown = nla_get_u8(tb[IDIAG_ATTR_SHUTDOWN]);
if (tb[INET_DIAG_SHUTDOWN]) {
msg->idiag_shutdown = nla_get_u8(tb[INET_DIAG_SHUTDOWN]);
msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
}
if (tb[IDIAG_ATTR_CONG])
msg->idiag_cong = nla_strdup(tb[IDIAG_ATTR_CONG]);
if (tb[INET_DIAG_CONG]) {
msg->idiag_cong = nla_strdup(tb[INET_DIAG_CONG]);
msg->ce_mask |= IDIAGNL_ATTR_CONG;
}
if (tb[IDIAG_ATTR_INFO])
nla_memcpy(&msg->idiag_tcpinfo, tb[IDIAG_ATTR_INFO],
if (tb[INET_DIAG_INFO]) {
nla_memcpy(&msg->idiag_tcpinfo, tb[INET_DIAG_INFO],
sizeof(msg->idiag_tcpinfo));
msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
}
if (tb[IDIAG_ATTR_MEMINFO]) {
if (tb[INET_DIAG_MEMINFO]) {
struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc();
struct inet_diag_meminfo *raw_minfo = NULL;
@ -668,7 +772,7 @@ int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
goto errout_nomem;
raw_minfo = (struct inet_diag_meminfo *)
nla_data(tb[IDIAG_ATTR_MEMINFO]);
nla_data(tb[INET_DIAG_MEMINFO]);
idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem);
idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem);
@ -676,9 +780,10 @@ int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem);
msg->idiag_meminfo = minfo;
msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
}
if (tb[IDIAG_ATTR_VEGASINFO]) {
if (tb[INET_DIAG_VEGASINFO]) {
struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc();
struct tcpvegas_info *raw_vinfo = NULL;
@ -686,7 +791,7 @@ int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
goto errout_nomem;
raw_vinfo = (struct tcpvegas_info *)
nla_data(tb[IDIAG_ATTR_VEGASINFO]);
nla_data(tb[INET_DIAG_VEGASINFO]);
idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled);
idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt);
@ -694,11 +799,14 @@ int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt);
msg->idiag_vegasinfo = vinfo;
msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
}
if (tb[IDIAG_ATTR_SKMEMINFO])
nla_memcpy(&msg->idiag_skmeminfo, tb[IDIAG_ATTR_SKMEMINFO],
if (tb[INET_DIAG_SKMEMINFO]) {
nla_memcpy(&msg->idiag_skmeminfo, tb[INET_DIAG_SKMEMINFO],
sizeof(msg->idiag_skmeminfo));
msg->ce_mask |= IDIAGNL_ATTR_SKMEMINFO;
}
*result = msg;
return 0;
@ -712,6 +820,53 @@ errout_nomem:
goto errout;
}
static const struct trans_tbl idiagnl_attrs[] = {
__ADD(IDIAGNL_ATTR_FAMILY, family),
__ADD(IDIAGNL_ATTR_STATE, state),
__ADD(IDIAGNL_ATTR_TIMER, timer),
__ADD(IDIAGNL_ATTR_RETRANS, retrans),
__ADD(IDIAGNL_ATTR_SPORT, sport),
__ADD(IDIAGNL_ATTR_DPORT, dport),
__ADD(IDIAGNL_ATTR_SRC, src),
__ADD(IDIAGNL_ATTR_DST, dst),
__ADD(IDIAGNL_ATTR_IFINDEX, ifindex),
__ADD(IDIAGNL_ATTR_EXPIRES, expires),
__ADD(IDIAGNL_ATTR_RQUEUE, rqueue),
__ADD(IDIAGNL_ATTR_WQUEUE, wqueue),
__ADD(IDIAGNL_ATTR_UID, uid),
__ADD(IDIAGNL_ATTR_INODE, inode),
__ADD(IDIAGNL_ATTR_TOS, tos),
__ADD(IDIAGNL_ATTR_TCLASS, tclass),
__ADD(IDIAGNL_ATTR_SHUTDOWN, shutdown),
__ADD(IDIAGNL_ATTR_CONG, cong),
__ADD(IDIAGNL_ATTR_MEMINFO, meminfo),
__ADD(IDIAGNL_ATTR_VEGASINFO, vegasinfo),
__ADD(IDIAGNL_ATTR_TCPINFO, tcpinfo),
__ADD(IDIAGNL_ATTR_SKMEMINFO, skmeminfo),
};
static char *_idiagnl_attrs2str(int attrs, char *buf, size_t len)
{
return __flags2str(attrs, buf, len, idiagnl_attrs,
ARRAY_SIZE(idiagnl_attrs));
}
static int idiagnl_compare(struct nl_object *_a, struct nl_object *_b,
uint32_t attrs, int flags)
{
struct idiagnl_msg *a = (struct idiagnl_msg *) _a;
struct idiagnl_msg *b = (struct idiagnl_msg *) _b;
int diff = 0;
#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, IDIAGNL_ATTR_##ATTR, a, b, EXPR)
diff |= _DIFF(FAMILY, a->idiag_family != b->idiag_family);
diff |= _DIFF(STATE, a->idiag_state != b->idiag_state);
diff |= _DIFF(SPORT, a->idiag_sport != b->idiag_sport);
diff |= _DIFF(DPORT, a->idiag_dport != b->idiag_dport);
#undef _DIFF
return diff;
}
static void idiagnl_keygen(struct nl_object *obj, uint32_t *hashkey,
uint32_t table_sz)
{
@ -749,9 +904,13 @@ struct nl_object_ops idiagnl_msg_obj_ops = {
[NL_DUMP_DETAILS] = idiag_msg_dump_details,
[NL_DUMP_STATS] = idiag_msg_dump_stats,
},
.oo_compare = idiagnl_compare,
.oo_keygen = idiagnl_keygen,
.oo_attrs2str = idiagnl_attrs2str,
.oo_id_attrs = (IDIAG_ATTR_INFO)
.oo_attrs2str = _idiagnl_attrs2str,
.oo_id_attrs = (IDIAGNL_ATTR_FAMILY |
IDIAGNL_ATTR_STATE |
IDIAGNL_ATTR_SPORT |
IDIAGNL_ATTR_DPORT),
};
/** @endcond */

View file

@ -83,22 +83,10 @@ void idiagnl_vegasinfo_set_minrtt(struct idiagnl_vegasinfo *vinfo, uint32_t
}
/** @} */
static int idiagnl_vegasinfo_clone(struct nl_object *_dst,
struct nl_object *_src)
{
struct idiagnl_vegasinfo *dst = (struct idiagnl_vegasinfo *) _dst;
struct idiagnl_vegasinfo *src = (struct idiagnl_vegasinfo *) _src;
memcpy(dst, src, sizeof(struct idiagnl_vegasinfo));
return 0;
}
/** @cond SKIP */
struct nl_object_ops idiagnl_vegasinfo_obj_ops = {
.oo_name = "idiag/idiag_vegasinfo",
.oo_size = sizeof(struct idiagnl_vegasinfo),
.oo_clone = idiagnl_vegasinfo_clone,
};
/** @endcond */
/** @} */

View file

@ -72,7 +72,7 @@ int main(int argc, char *argv[])
}
}
if ((err = idiagnl_msg_alloc_cache(sock, AF_INET, IDIAG_SS_ALL,
if ((err = idiagnl_msg_alloc_cache(sock, AF_INET, IDIAGNL_SS_ALL,
&idiag_cache))) {
nl_cli_fatal(err, "Unable to allocate idiag msg cache: %s",
nl_geterror(err));