8#include <linux/inet_diag.h>
10#include <netlink/hashtable.h>
11#include <netlink/idiag/msg.h>
12#include <netlink/idiag/meminfo.h>
13#include <netlink/idiag/vegasinfo.h>
14#include <netlink/idiag/idiagnl.h>
17#include "nl-priv-dynamic-core/nl-core.h"
18#include "nl-aux-core/nl-core.h"
19#include "nl-priv-dynamic-core/cache-api.h"
28 uint8_t idiag_retrans;
31 struct nl_addr * idiag_src;
32 struct nl_addr * idiag_dst;
33 uint32_t idiag_ifindex;
34 uint32_t idiag_expires;
35 uint32_t idiag_rqueue;
36 uint32_t idiag_wqueue;
42 uint8_t idiag_shutdown;
46 struct tcp_info idiag_tcpinfo;
47 uint32_t idiag_skmeminfo[SK_MEMINFO_VARS];
50#define IDIAGNL_ATTR_FAMILY (0x1 << 1)
51#define IDIAGNL_ATTR_STATE (0x1 << 2)
52#define IDIAGNL_ATTR_TIMER (0x1 << 3)
53#define IDIAGNL_ATTR_RETRANS (0x1 << 4)
54#define IDIAGNL_ATTR_SPORT (0x1 << 5)
55#define IDIAGNL_ATTR_DPORT (0x1 << 6)
56#define IDIAGNL_ATTR_SRC (0x1 << 7)
57#define IDIAGNL_ATTR_DST (0x1 << 8)
58#define IDIAGNL_ATTR_IFINDEX (0x1 << 9)
59#define IDIAGNL_ATTR_EXPIRES (0x1 << 10)
60#define IDIAGNL_ATTR_RQUEUE (0x1 << 11)
61#define IDIAGNL_ATTR_WQUEUE (0x1 << 12)
62#define IDIAGNL_ATTR_UID (0x1 << 13)
63#define IDIAGNL_ATTR_INODE (0x1 << 14)
64#define IDIAGNL_ATTR_TOS (0x1 << 15)
65#define IDIAGNL_ATTR_TCLASS (0x1 << 16)
66#define IDIAGNL_ATTR_SHUTDOWN (0x1 << 17)
67#define IDIAGNL_ATTR_CONG (0x1 << 18)
68#define IDIAGNL_ATTR_MEMINFO (0x1 << 19)
69#define IDIAGNL_ATTR_VEGASINFO (0x1 << 20)
70#define IDIAGNL_ATTR_TCPINFO (0x1 << 21)
71#define IDIAGNL_ATTR_SKMEMINFO (0x1 << 22)
73#define _INET_DIAG_ALL ((1<<(INET_DIAG_MAX+1))-1)
84struct idiagnl_msg *idiagnl_msg_alloc(
void)
89void idiagnl_msg_get(
struct idiagnl_msg *msg)
94void idiagnl_msg_put(
struct idiagnl_msg *msg)
99static struct nl_cache_ops idiagnl_msg_ops;
101static int idiagnl_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
102 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
104 struct idiagnl_msg *msg = NULL;
107 if ((err = idiagnl_msg_parse(nlh, &msg)) < 0)
110 err = pp->pp_cb((
struct nl_object *) msg, pp);
111 idiagnl_msg_put(msg);
116static int idiagnl_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
118 int family = cache->c_iarg1;
119 int states = cache->c_iarg2;
134static struct nl_cache_ops idiagnl_msg_ops = {
135 .co_name =
"idiag/idiag",
136 .co_hdrsize =
sizeof(
struct inet_diag_msg),
138 { TCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
139 { DCCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
140 END_OF_MSGTYPES_LIST,
142 .co_protocol = NETLINK_INET_DIAG,
143 .co_request_update = idiagnl_request_update,
144 .co_msg_parser = idiagnl_msg_parser,
145 .co_obj_ops = &idiagnl_msg_obj_ops,
148static void _nl_init idiagnl_init(
void)
153static void _nl_exit idiagnl_exit(
void)
175 struct nl_cache **result)
177 struct nl_cache *cache = NULL;
183 cache->c_iarg1 = family;
184 cache->c_iarg2 = states;
202uint8_t idiagnl_msg_get_family(
const struct idiagnl_msg *msg)
204 return msg->idiag_family;
207void idiagnl_msg_set_family(
struct idiagnl_msg *msg, uint8_t family)
209 msg->idiag_family = family;
210 msg->ce_mask |= IDIAGNL_ATTR_FAMILY;
213uint8_t idiagnl_msg_get_state(
const struct idiagnl_msg *msg)
215 return msg->idiag_state;
218void idiagnl_msg_set_state(
struct idiagnl_msg *msg, uint8_t state)
220 msg->idiag_state = state;
221 msg->ce_mask |= IDIAGNL_ATTR_STATE;
224uint8_t idiagnl_msg_get_timer(
const struct idiagnl_msg *msg)
226 return msg->idiag_timer;
229void idiagnl_msg_set_timer(
struct idiagnl_msg *msg, uint8_t timer)
231 msg->idiag_timer = timer;
232 msg->ce_mask |= IDIAGNL_ATTR_TIMER;
235uint8_t idiagnl_msg_get_retrans(
const struct idiagnl_msg *msg)
237 return msg->idiag_retrans;
240void idiagnl_msg_set_retrans(
struct idiagnl_msg *msg, uint8_t retrans)
242 msg->idiag_retrans = retrans;
243 msg->ce_mask |= IDIAGNL_ATTR_RETRANS;
246uint16_t idiagnl_msg_get_sport(
struct idiagnl_msg *msg)
248 return msg->idiag_sport;
251void idiagnl_msg_set_sport(
struct idiagnl_msg *msg, uint16_t port)
253 msg->idiag_sport = port;
254 msg->ce_mask |= IDIAGNL_ATTR_SPORT;
257uint16_t idiagnl_msg_get_dport(
struct idiagnl_msg *msg)
259 return msg->idiag_dport;
262void idiagnl_msg_set_dport(
struct idiagnl_msg *msg, uint16_t port)
264 msg->idiag_dport = port;
265 msg->ce_mask |= IDIAGNL_ATTR_DPORT;
268struct nl_addr *idiagnl_msg_get_src(
const struct idiagnl_msg *msg)
270 return msg->idiag_src;
273int idiagnl_msg_set_src(
struct idiagnl_msg *msg,
struct nl_addr *addr)
279 msg->idiag_src = addr;
280 msg->ce_mask |= IDIAGNL_ATTR_SRC;
285struct nl_addr *idiagnl_msg_get_dst(
const struct idiagnl_msg *msg)
287 return msg->idiag_dst;
290int idiagnl_msg_set_dst(
struct idiagnl_msg *msg,
struct nl_addr *addr)
296 msg->idiag_dst = addr;
297 msg->ce_mask |= IDIAGNL_ATTR_DST;
302uint32_t idiagnl_msg_get_ifindex(
const struct idiagnl_msg *msg)
304 return msg->idiag_ifindex;
307void idiagnl_msg_set_ifindex(
struct idiagnl_msg *msg, uint32_t ifindex)
309 msg->idiag_ifindex = ifindex;
310 msg->ce_mask |= IDIAGNL_ATTR_IFINDEX;
313uint32_t idiagnl_msg_get_expires(
const struct idiagnl_msg *msg)
315 return msg->idiag_expires;
318void idiagnl_msg_set_expires(
struct idiagnl_msg *msg, uint32_t expires)
320 msg->idiag_expires = expires;
321 msg->ce_mask |= IDIAGNL_ATTR_EXPIRES;
324uint32_t idiagnl_msg_get_rqueue(
const struct idiagnl_msg *msg)
326 return msg->idiag_rqueue;
329void idiagnl_msg_set_rqueue(
struct idiagnl_msg *msg, uint32_t rqueue)
331 msg->idiag_rqueue = rqueue;
332 msg->ce_mask |= IDIAGNL_ATTR_RQUEUE;
335uint32_t idiagnl_msg_get_wqueue(
const struct idiagnl_msg *msg)
337 return msg->idiag_wqueue;
340void idiagnl_msg_set_wqueue(
struct idiagnl_msg *msg, uint32_t wqueue)
342 msg->idiag_wqueue = wqueue;
343 msg->ce_mask |= IDIAGNL_ATTR_WQUEUE;
346uint32_t idiagnl_msg_get_uid(
const struct idiagnl_msg *msg)
348 return msg->idiag_uid;
351void idiagnl_msg_set_uid(
struct idiagnl_msg *msg, uint32_t uid)
353 msg->idiag_uid = uid;
354 msg->ce_mask |= IDIAGNL_ATTR_UID;
357uint32_t idiagnl_msg_get_inode(
const struct idiagnl_msg *msg)
359 return msg->idiag_inode;
362void idiagnl_msg_set_inode(
struct idiagnl_msg *msg, uint32_t inode)
364 msg->idiag_inode = inode;
365 msg->ce_mask |= IDIAGNL_ATTR_INODE;
368uint8_t idiagnl_msg_get_tos(
const struct idiagnl_msg *msg)
370 return msg->idiag_tos;
373void idiagnl_msg_set_tos(
struct idiagnl_msg *msg, uint8_t tos)
375 msg->idiag_tos = tos;
376 msg->ce_mask |= IDIAGNL_ATTR_TOS;
379uint8_t idiagnl_msg_get_tclass(
const struct idiagnl_msg *msg)
381 return msg->idiag_tclass;
384void idiagnl_msg_set_tclass(
struct idiagnl_msg *msg, uint8_t tclass)
386 msg->idiag_tclass = tclass;
387 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
390uint8_t idiagnl_msg_get_shutdown(
const struct idiagnl_msg *msg)
392 return msg->idiag_shutdown;
395void idiagnl_msg_set_shutdown(
struct idiagnl_msg *msg, uint8_t shutdown)
397 msg->idiag_shutdown = shutdown;
398 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
401char *idiagnl_msg_get_cong(
const struct idiagnl_msg *msg)
403 return msg->idiag_cong;
406void idiagnl_msg_set_cong(
struct idiagnl_msg *msg,
char *cong)
408 free (msg->idiag_cong);
409 msg->idiag_cong = strdup(cong);
410 msg->ce_mask |= IDIAGNL_ATTR_CONG;
413struct idiagnl_meminfo *idiagnl_msg_get_meminfo(
const struct idiagnl_msg *msg)
415 return msg->idiag_meminfo;
418void idiagnl_msg_set_meminfo(
struct idiagnl_msg *msg,
struct idiagnl_meminfo *minfo)
420 if (msg->idiag_meminfo)
421 idiagnl_meminfo_put(msg->idiag_meminfo);
423 idiagnl_meminfo_get(minfo);
424 msg->idiag_meminfo = minfo;
425 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
428struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(
const struct idiagnl_msg *msg)
430 return msg->idiag_vegasinfo;
433void idiagnl_msg_set_vegasinfo(
struct idiagnl_msg *msg,
struct idiagnl_vegasinfo *vinfo)
435 if (msg->idiag_vegasinfo)
436 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
438 idiagnl_vegasinfo_get(vinfo);
439 msg->idiag_vegasinfo = vinfo;
440 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
443struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
445 return msg->idiag_tcpinfo;
448void idiagnl_msg_set_tcpinfo(
struct idiagnl_msg *msg,
struct tcp_info *tinfo)
450 memcpy(&msg->idiag_tcpinfo, tinfo,
sizeof(
struct tcp_info));
451 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
456static void idiag_msg_dump_line(
struct nl_object *a,
struct nl_dump_params *p)
458 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
459 char buf[64] = { 0 };
461 nl_dump_line(p,
"family: %s ", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
463 ntohs(msg->idiag_sport));
465 ntohs(msg->idiag_dport));
466 nl_dump(p,
"iif: %d ", msg->idiag_ifindex);
470static void idiag_msg_dump_details(
struct nl_object *a,
struct nl_dump_params *p)
472 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
473 char buf[64], buf2[64];
475 nl_dump(p,
"\nfamily: %s\n", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
478 nl_dump(p,
"timer (%s, %s, retransmits: %d)\n",
480 nl_msec2str(msg->idiag_expires, buf2,
sizeof(buf2)),
484 ntohs(msg->idiag_sport));
486 ntohs(msg->idiag_dport));
488 nl_dump(p,
"ifindex: %d\n", msg->idiag_ifindex);
489 nl_dump(p,
"rqueue: %-6d wqueue: %-6d\n", msg->idiag_rqueue, msg->idiag_wqueue);
490 nl_dump(p,
"uid %d\n", msg->idiag_uid);
491 nl_dump(p,
"inode %d\n", msg->idiag_inode);
492 if (msg->idiag_shutdown) {
493 nl_dump(p,
"socket shutdown: %s\n",
498 nl_dump(p,
"tos: 0x%x\n", msg->idiag_tos);
499 nl_dump(p,
"traffic class: %d\n", msg->idiag_tclass);
500 nl_dump(p,
"congestion algorithm: %s\n", msg->idiag_cong ? msg->idiag_cong :
"");
503static void idiag_msg_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
505 struct idiagnl_msg *msg = (
struct idiagnl_msg *) obj;
508 idiag_msg_dump_details(obj, p);
511 nl_dump(p,
"\tsocket state: %s\n",
514 nl_dump(p,
"\ttcp state: %s\n",
517 nl_dump(p,
"\tretransmits: %d\n",
518 msg->idiag_tcpinfo.tcpi_retransmits);
520 msg->idiag_tcpinfo.tcpi_probes);
522 msg->idiag_tcpinfo.tcpi_backoff);
526 nl_dump(p,
"\tsnd_wscale: %d\n", msg->idiag_tcpinfo.tcpi_snd_wscale);
527 nl_dump(p,
"\trcv_wscale: %d\n", msg->idiag_tcpinfo.tcpi_rcv_wscale);
528 nl_dump(p,
"\trto: %d\n", msg->idiag_tcpinfo.tcpi_rto);
529 nl_dump(p,
"\tato: %d\n", msg->idiag_tcpinfo.tcpi_ato);
534 nl_dump(p,
"\tunacked: %d\n", msg->idiag_tcpinfo.tcpi_unacked);
535 nl_dump(p,
"\tsacked: %d\n", msg->idiag_tcpinfo.tcpi_sacked);
537 nl_dump(p,
"\tlost: %d\n", msg->idiag_tcpinfo.tcpi_lost);
538 nl_dump(p,
"\tretransmit segments: %d\n",
539 msg->idiag_tcpinfo.tcpi_retrans);
541 msg->idiag_tcpinfo.tcpi_fackets);
542 nl_dump(p,
"\tlast data sent: %s\n",
543 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_sent, buf,
545 nl_dump(p,
"\tlast ack sent: %s\n",
546 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_sent, buf,
sizeof(buf)));
547 nl_dump(p,
"\tlast data recv: %s\n",
548 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_recv, buf,
550 nl_dump(p,
"\tlast ack recv: %s\n",
551 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_recv, buf,
556 nl_dump(p,
"\trcv ss threshold: %d\n",
557 msg->idiag_tcpinfo.tcpi_rcv_ssthresh);
558 nl_dump(p,
"\tsmoothed round trip time: %d\n",
559 msg->idiag_tcpinfo.tcpi_rtt);
560 nl_dump(p,
"\tround trip time variation: %d\n",
561 msg->idiag_tcpinfo.tcpi_rttvar);
562 nl_dump(p,
"\tsnd ss threshold: %s\n",
563 nl_size2str(msg->idiag_tcpinfo.tcpi_snd_ssthresh, buf,
565 nl_dump(p,
"\tsend congestion window: %d\n",
566 msg->idiag_tcpinfo.tcpi_snd_cwnd);
567 nl_dump(p,
"\tadvertised mss: %s\n",
570 nl_dump(p,
"\treordering: %d\n",
571 msg->idiag_tcpinfo.tcpi_reordering);
572 nl_dump(p,
"\trcv rround trip time: %d\n",
573 msg->idiag_tcpinfo.tcpi_rcv_rtt);
574 nl_dump(p,
"\treceive queue space: %s\n",
575 nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_space, buf,
577 nl_dump(p,
"\ttotal retransmits: %d\n",
578 msg->idiag_tcpinfo.tcpi_total_retrans);
581 if (msg->idiag_meminfo) {
602 if (msg->idiag_vegasinfo) {
604 nl_dump(p,
"\tvegas enabled: %d\n",
605 msg->idiag_vegasinfo->tcpv_enabled);
606 if (msg->idiag_vegasinfo->tcpv_enabled) {
608 msg->idiag_vegasinfo->tcpv_rttcnt);
609 nl_dump(p,
"\trtt (propagation delay): %d",
610 msg->idiag_vegasinfo->tcpv_rtt);
612 msg->idiag_vegasinfo->tcpv_minrtt);
617 if (msg->ce_mask & IDIAGNL_ATTR_MEMINFO) {
619 nl_dump(p,
"\trmem alloc: %d\n",
620 msg->idiag_skmeminfo[SK_MEMINFO_RMEM_ALLOC]);
622 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_RCVBUF],
624 nl_dump(p,
"\twmem alloc: %d\n",
625 msg->idiag_skmeminfo[SK_MEMINFO_WMEM_ALLOC]);
627 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_SNDBUF],
629 nl_dump(p,
"\tfwd alloc: %d\n",
630 msg->idiag_skmeminfo[SK_MEMINFO_FWD_ALLOC]);
631 nl_dump(p,
"\twmem queued: %s\n",
632 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_WMEM_QUEUED],
635 msg->idiag_skmeminfo[SK_MEMINFO_OPTMEM]);
637 msg->idiag_skmeminfo[SK_MEMINFO_BACKLOG]);
642static void idiagnl_msg_free(
struct nl_object *a)
644 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
648 free(msg->idiag_cong);
651 idiagnl_meminfo_put(msg->idiag_meminfo);
652 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
655static int idiagnl_msg_clone(
struct nl_object *_dst,
struct nl_object *_src)
657 struct idiagnl_msg *dst = (
struct idiagnl_msg *) _dst;
658 struct idiagnl_msg *src = (
struct idiagnl_msg *) _src;
660 dst->idiag_src = NULL;
661 dst->idiag_dst = NULL;
662 dst->idiag_cong = NULL;
663 dst->idiag_meminfo = NULL;
664 dst->idiag_vegasinfo = NULL;
665 dst->ce_mask &= ~(IDIAGNL_ATTR_CONG |
668 IDIAGNL_ATTR_MEMINFO |
669 IDIAGNL_ATTR_VEGASINFO);
671 if (src->idiag_cong) {
672 if (!(dst->idiag_cong = strdup(src->idiag_cong)))
674 dst->ce_mask |= IDIAGNL_ATTR_CONG;
677 if (src->idiag_src) {
680 dst->ce_mask |= IDIAGNL_ATTR_SRC;
683 if (src->idiag_dst) {
686 dst->ce_mask |= IDIAGNL_ATTR_DST;
689 if (src->idiag_meminfo) {
692 dst->ce_mask |= IDIAGNL_ATTR_MEMINFO;
695 if (src->idiag_vegasinfo) {
698 dst->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
706 [INET_DIAG_INFO] = { .minlen =
sizeof(
struct tcp_info) },
707 [INET_DIAG_VEGASINFO] = { .minlen =
sizeof(
struct tcpvegas_info) },
709 [INET_DIAG_TOS] = { .type =
NLA_U8 },
710 [INET_DIAG_TCLASS] = { .type =
NLA_U8 },
712 [INET_DIAG_SKMEMINFO] = { .minlen = (
sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) },
713 [INET_DIAG_SHUTDOWN] = { .type =
NLA_U8 },
716int idiagnl_msg_parse(
struct nlmsghdr *nlh,
struct idiagnl_msg **result)
718 struct idiagnl_msg *msg = NULL;
719 struct inet_diag_msg *raw_msg = NULL;
720 struct nl_addr *src = NULL, *dst = NULL;
721 struct nlattr *tb[INET_DIAG_MAX+1];
724 msg = idiagnl_msg_alloc();
728 err =
nlmsg_parse(nlh,
sizeof(
struct inet_diag_msg), tb, INET_DIAG_MAX,
734 msg->idiag_family = raw_msg->idiag_family;
735 msg->idiag_state = raw_msg->idiag_state;
736 msg->idiag_timer = raw_msg->idiag_timer;
737 msg->idiag_retrans = raw_msg->idiag_retrans;
738 msg->idiag_expires = raw_msg->idiag_expires;
739 msg->idiag_rqueue = raw_msg->idiag_rqueue;
740 msg->idiag_wqueue = raw_msg->idiag_wqueue;
741 msg->idiag_uid = raw_msg->idiag_uid;
742 msg->idiag_inode = raw_msg->idiag_inode;
743 msg->idiag_sport = raw_msg->id.idiag_sport;
744 msg->idiag_dport = raw_msg->id.idiag_dport;
745 msg->idiag_ifindex = raw_msg->id.idiag_if;
747 msg->ce_mask = (IDIAGNL_ATTR_FAMILY |
750 IDIAGNL_ATTR_RETRANS |
751 IDIAGNL_ATTR_EXPIRES |
752 IDIAGNL_ATTR_RQUEUE |
753 IDIAGNL_ATTR_WQUEUE |
758 IDIAGNL_ATTR_IFINDEX);
760 dst =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
761 sizeof(raw_msg->id.idiag_dst));
765 err = idiagnl_msg_set_dst(msg, dst);
771 src =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src,
772 sizeof(raw_msg->id.idiag_src));
776 err = idiagnl_msg_set_src(msg, src);
782 if (tb[INET_DIAG_TOS]) {
783 msg->idiag_tos =
nla_get_u8(tb[INET_DIAG_TOS]);
784 msg->ce_mask |= IDIAGNL_ATTR_TOS;
787 if (tb[INET_DIAG_TCLASS]) {
788 msg->idiag_tclass =
nla_get_u8(tb[INET_DIAG_TCLASS]);
789 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
792 if (tb[INET_DIAG_SHUTDOWN]) {
793 msg->idiag_shutdown =
nla_get_u8(tb[INET_DIAG_SHUTDOWN]);
794 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
797 if (tb[INET_DIAG_CONG]) {
798 msg->idiag_cong = nla_strdup(tb[INET_DIAG_CONG]);
799 msg->ce_mask |= IDIAGNL_ATTR_CONG;
802 if (tb[INET_DIAG_INFO]) {
803 nla_memcpy(&msg->idiag_tcpinfo, tb[INET_DIAG_INFO],
804 sizeof(msg->idiag_tcpinfo));
805 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
808 if (tb[INET_DIAG_MEMINFO]) {
810 struct inet_diag_meminfo *raw_minfo = NULL;
815 raw_minfo = (
struct inet_diag_meminfo *)
818 idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem);
819 idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem);
820 idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem);
821 idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem);
823 msg->idiag_meminfo = minfo;
824 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
827 if (tb[INET_DIAG_VEGASINFO]) {
829 struct tcpvegas_info *raw_vinfo = NULL;
834 raw_vinfo = (
struct tcpvegas_info *)
837 idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled);
838 idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt);
839 idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt);
840 idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt);
842 msg->idiag_vegasinfo = vinfo;
843 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
846 if (tb[INET_DIAG_SKMEMINFO]) {
847 nla_memcpy(&msg->idiag_skmeminfo, tb[INET_DIAG_SKMEMINFO],
848 sizeof(msg->idiag_skmeminfo));
849 msg->ce_mask |= IDIAGNL_ATTR_SKMEMINFO;
856 idiagnl_msg_put(msg);
864static const struct trans_tbl idiagnl_attrs[] = {
865 __ADD(IDIAGNL_ATTR_FAMILY, family),
866 __ADD(IDIAGNL_ATTR_STATE, state),
867 __ADD(IDIAGNL_ATTR_TIMER, timer),
868 __ADD(IDIAGNL_ATTR_RETRANS, retrans),
869 __ADD(IDIAGNL_ATTR_SPORT, sport),
870 __ADD(IDIAGNL_ATTR_DPORT, dport),
871 __ADD(IDIAGNL_ATTR_SRC, src),
872 __ADD(IDIAGNL_ATTR_DST, dst),
873 __ADD(IDIAGNL_ATTR_IFINDEX, ifindex),
874 __ADD(IDIAGNL_ATTR_EXPIRES, expires),
875 __ADD(IDIAGNL_ATTR_RQUEUE, rqueue),
876 __ADD(IDIAGNL_ATTR_WQUEUE, wqueue),
877 __ADD(IDIAGNL_ATTR_UID, uid),
878 __ADD(IDIAGNL_ATTR_INODE, inode),
879 __ADD(IDIAGNL_ATTR_TOS, tos),
880 __ADD(IDIAGNL_ATTR_TCLASS, tclass),
881 __ADD(IDIAGNL_ATTR_SHUTDOWN, shutdown),
882 __ADD(IDIAGNL_ATTR_CONG, cong),
883 __ADD(IDIAGNL_ATTR_MEMINFO, meminfo),
884 __ADD(IDIAGNL_ATTR_VEGASINFO, vegasinfo),
885 __ADD(IDIAGNL_ATTR_TCPINFO, tcpinfo),
886 __ADD(IDIAGNL_ATTR_SKMEMINFO, skmeminfo),
889static char *_idiagnl_attrs2str(
int attrs,
char *buf,
size_t len)
891 return __flags2str(attrs, buf, len, idiagnl_attrs,
892 ARRAY_SIZE(idiagnl_attrs));
895static uint64_t idiagnl_compare(
struct nl_object *_a,
struct nl_object *_b,
896 uint64_t attrs,
int flags)
898 struct idiagnl_msg *a = (
struct idiagnl_msg *) _a;
899 struct idiagnl_msg *b = (
struct idiagnl_msg *) _b;
902#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
903 diff |= _DIFF(IDIAGNL_ATTR_FAMILY, a->idiag_family != b->idiag_family);
904 diff |= _DIFF(IDIAGNL_ATTR_STATE, a->idiag_state != b->idiag_state);
905 diff |= _DIFF(IDIAGNL_ATTR_TIMER, a->idiag_timer != b->idiag_timer);
906 diff |= _DIFF(IDIAGNL_ATTR_RETRANS,
907 a->idiag_retrans != b->idiag_retrans);
908 diff |= _DIFF(IDIAGNL_ATTR_SPORT, a->idiag_sport != b->idiag_sport);
909 diff |= _DIFF(IDIAGNL_ATTR_DPORT, a->idiag_dport != b->idiag_dport);
910 diff |= _DIFF(IDIAGNL_ATTR_SRC,
912 diff |= _DIFF(IDIAGNL_ATTR_DST,
914 diff |= _DIFF(IDIAGNL_ATTR_IFINDEX,
915 a->idiag_ifindex != b->idiag_ifindex);
916 diff |= _DIFF(IDIAGNL_ATTR_EXPIRES,
917 a->idiag_expires != b->idiag_expires);
918 diff |= _DIFF(IDIAGNL_ATTR_RQUEUE, a->idiag_rqueue != b->idiag_rqueue);
919 diff |= _DIFF(IDIAGNL_ATTR_WQUEUE, a->idiag_wqueue != b->idiag_wqueue);
920 diff |= _DIFF(IDIAGNL_ATTR_UID, a->idiag_uid != b->idiag_uid);
921 diff |= _DIFF(IDIAGNL_ATTR_INODE, a->idiag_inode != b->idiag_inode);
922 diff |= _DIFF(IDIAGNL_ATTR_TOS, a->idiag_tos != b->idiag_tos);
923 diff |= _DIFF(IDIAGNL_ATTR_TCLASS, a->idiag_tclass != b->idiag_tclass);
924 diff |= _DIFF(IDIAGNL_ATTR_SHUTDOWN,
925 a->idiag_shutdown != b->idiag_shutdown);
926 diff |= _DIFF(IDIAGNL_ATTR_CONG, strcmp(a->idiag_cong, b->idiag_cong));
927 diff |= _DIFF(IDIAGNL_ATTR_MEMINFO,
929 (
struct nl_object *)b->idiag_meminfo));
930 diff |= _DIFF(IDIAGNL_ATTR_VEGASINFO,
932 (
struct nl_object *)b->idiag_vegasinfo));
933 diff |= _DIFF(IDIAGNL_ATTR_TCPINFO,
934 memcmp(&a->idiag_tcpinfo, &b->idiag_tcpinfo,
935 sizeof(a->idiag_tcpinfo)));
936 diff |= _DIFF(IDIAGNL_ATTR_SKMEMINFO,
937 memcmp(a->idiag_skmeminfo, b->idiag_skmeminfo,
938 sizeof(a->idiag_skmeminfo)));
944static void idiagnl_keygen(
struct nl_object *obj, uint32_t *hashkey,
947 struct idiagnl_msg *msg = (
struct idiagnl_msg *)obj;
949 struct idiagnl_hash_key {
957 key_sz =
sizeof(key);
958 key.family = msg->idiag_family;
961 key.sport = msg->idiag_sport;
962 key.dport = msg->idiag_dport;
964 if (msg->idiag_src) {
968 if (msg->idiag_dst) {
973 *hashkey = nl_hash(&key, key_sz, 0) % table_sz;
975 NL_DBG(5,
"idiagnl %p key (fam %d src_hash %d dst_hash %d sport %d dport %d) keysz %d, hash 0x%x\n",
976 msg, key.family, key.src_hash, key.dst_hash, key.sport, key.dport, key_sz, *hashkey);
982struct nl_object_ops idiagnl_msg_obj_ops = {
983 .oo_name =
"idiag/idiag_msg",
984 .oo_size =
sizeof(
struct idiagnl_msg),
985 .oo_free_data = idiagnl_msg_free,
986 .oo_clone = idiagnl_msg_clone,
992 .oo_compare = idiagnl_compare,
993 .oo_keygen = idiagnl_keygen,
994 .oo_attrs2str = _idiagnl_attrs2str,
995 .oo_id_attrs = (IDIAGNL_ATTR_FAMILY |
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
@ NLA_STRING
NUL terminated character string.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.
char * idiagnl_timer2str(int timer, char *buf, size_t len)
Convert inet diag timer types to strings.
char * idiagnl_shutdown2str(uint8_t shutdown, char *buf, size_t len)
Convert shutdown state to string.
char * idiagnl_state2str(int state, char *buf, size_t len)
Convert inet diag socket states to strings.
int idiagnl_send_simple(struct nl_sock *sk, int flags, uint8_t family, uint16_t states, uint16_t ext)
Send trivial idiag netlink message.
char * idiagnl_tcpstate2str(uint8_t state, char *buf, size_t len)
Convert inetdiag tcp states to strings.
char * idiagnl_tcpopts2str(uint8_t attrs, char *buf, size_t len)
Convert TCP option attributes to string.
int idiagnl_msg_alloc_cache(struct nl_sock *sk, int family, int states, struct nl_cache **result)
Build an inetdiag cache to hold socket state information.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
Compute 32-bit bitmask representing difference in attribute values.
struct nl_object * nl_object_clone(struct nl_object *obj)
Allocate a new object and copy all data from an existing object.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
char * nl_size2str(const size_t size, char *buf, const size_t len)
Convert a size toa character string.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
char * nl_msec2str(uint64_t msec, char *buf, size_t len)
Convert milliseconds to a character string.
@ NL_DUMP_STATS
Dump all attributes including statistics.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t minlen
Minimal length of payload required.
uint16_t type
Type of attribute or NLA_UNSPEC.