6#include <netlink-private/netlink.h>
7#include <netlink/hashtable.h>
8#include <netlink/idiag/msg.h>
9#include <netlink/idiag/meminfo.h>
10#include <netlink/idiag/vegasinfo.h>
11#include <linux/inet_diag.h>
15#define IDIAGNL_ATTR_FAMILY (0x1 << 1)
16#define IDIAGNL_ATTR_STATE (0x1 << 2)
17#define IDIAGNL_ATTR_TIMER (0x1 << 3)
18#define IDIAGNL_ATTR_RETRANS (0x1 << 4)
19#define IDIAGNL_ATTR_SPORT (0x1 << 5)
20#define IDIAGNL_ATTR_DPORT (0x1 << 6)
21#define IDIAGNL_ATTR_SRC (0x1 << 7)
22#define IDIAGNL_ATTR_DST (0x1 << 8)
23#define IDIAGNL_ATTR_IFINDEX (0x1 << 9)
24#define IDIAGNL_ATTR_EXPIRES (0x1 << 10)
25#define IDIAGNL_ATTR_RQUEUE (0x1 << 11)
26#define IDIAGNL_ATTR_WQUEUE (0x1 << 12)
27#define IDIAGNL_ATTR_UID (0x1 << 13)
28#define IDIAGNL_ATTR_INODE (0x1 << 14)
29#define IDIAGNL_ATTR_TOS (0x1 << 15)
30#define IDIAGNL_ATTR_TCLASS (0x1 << 16)
31#define IDIAGNL_ATTR_SHUTDOWN (0x1 << 17)
32#define IDIAGNL_ATTR_CONG (0x1 << 18)
33#define IDIAGNL_ATTR_MEMINFO (0x1 << 19)
34#define IDIAGNL_ATTR_VEGASINFO (0x1 << 20)
35#define IDIAGNL_ATTR_TCPINFO (0x1 << 21)
36#define IDIAGNL_ATTR_SKMEMINFO (0x1 << 22)
38#define _INET_DIAG_ALL ((1<<(INET_DIAG_MAX+1))-1)
49struct idiagnl_msg *idiagnl_msg_alloc(
void)
54void idiagnl_msg_get(
struct idiagnl_msg *msg)
59void idiagnl_msg_put(
struct idiagnl_msg *msg)
64static struct nl_cache_ops idiagnl_msg_ops;
66static int idiagnl_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
67 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
69 struct idiagnl_msg *msg = NULL;
72 if ((err = idiagnl_msg_parse(nlh, &msg)) < 0)
75 err = pp->pp_cb((
struct nl_object *) msg, pp);
81static int idiagnl_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
83 int family = cache->c_iarg1;
84 int states = cache->c_iarg2;
99static struct nl_cache_ops idiagnl_msg_ops = {
100 .co_name =
"idiag/idiag",
101 .co_hdrsize =
sizeof(
struct inet_diag_msg),
103 { TCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
104 { DCCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
105 END_OF_MSGTYPES_LIST,
107 .co_protocol = NETLINK_INET_DIAG,
108 .co_request_update = idiagnl_request_update,
109 .co_msg_parser = idiagnl_msg_parser,
110 .co_obj_ops = &idiagnl_msg_obj_ops,
113static void __init idiagnl_init(
void)
118static void __exit idiagnl_exit(
void)
140 struct nl_cache **result)
142 struct nl_cache *cache = NULL;
148 cache->c_iarg1 = family;
149 cache->c_iarg2 = states;
167uint8_t idiagnl_msg_get_family(
const struct idiagnl_msg *msg)
169 return msg->idiag_family;
172void idiagnl_msg_set_family(
struct idiagnl_msg *msg, uint8_t family)
174 msg->idiag_family = family;
175 msg->ce_mask |= IDIAGNL_ATTR_FAMILY;
178uint8_t idiagnl_msg_get_state(
const struct idiagnl_msg *msg)
180 return msg->idiag_state;
183void idiagnl_msg_set_state(
struct idiagnl_msg *msg, uint8_t state)
185 msg->idiag_state = state;
186 msg->ce_mask |= IDIAGNL_ATTR_STATE;
189uint8_t idiagnl_msg_get_timer(
const struct idiagnl_msg *msg)
191 return msg->idiag_timer;
194void idiagnl_msg_set_timer(
struct idiagnl_msg *msg, uint8_t timer)
196 msg->idiag_timer = timer;
197 msg->ce_mask |= IDIAGNL_ATTR_TIMER;
200uint8_t idiagnl_msg_get_retrans(
const struct idiagnl_msg *msg)
202 return msg->idiag_retrans;
205void idiagnl_msg_set_retrans(
struct idiagnl_msg *msg, uint8_t retrans)
207 msg->idiag_retrans = retrans;
208 msg->ce_mask |= IDIAGNL_ATTR_RETRANS;
211uint16_t idiagnl_msg_get_sport(
struct idiagnl_msg *msg)
213 return msg->idiag_sport;
216void idiagnl_msg_set_sport(
struct idiagnl_msg *msg, uint16_t port)
218 msg->idiag_sport = port;
219 msg->ce_mask |= IDIAGNL_ATTR_SPORT;
222uint16_t idiagnl_msg_get_dport(
struct idiagnl_msg *msg)
224 return msg->idiag_dport;
227void idiagnl_msg_set_dport(
struct idiagnl_msg *msg, uint16_t port)
229 msg->idiag_dport = port;
230 msg->ce_mask |= IDIAGNL_ATTR_DPORT;
233struct nl_addr *idiagnl_msg_get_src(
const struct idiagnl_msg *msg)
235 return msg->idiag_src;
238int idiagnl_msg_set_src(
struct idiagnl_msg *msg,
struct nl_addr *addr)
244 msg->idiag_src = addr;
245 msg->ce_mask |= IDIAGNL_ATTR_SRC;
250struct nl_addr *idiagnl_msg_get_dst(
const struct idiagnl_msg *msg)
252 return msg->idiag_dst;
255int idiagnl_msg_set_dst(
struct idiagnl_msg *msg,
struct nl_addr *addr)
261 msg->idiag_dst = addr;
262 msg->ce_mask |= IDIAGNL_ATTR_DST;
267uint32_t idiagnl_msg_get_ifindex(
const struct idiagnl_msg *msg)
269 return msg->idiag_ifindex;
272void idiagnl_msg_set_ifindex(
struct idiagnl_msg *msg, uint32_t ifindex)
274 msg->idiag_ifindex = ifindex;
275 msg->ce_mask |= IDIAGNL_ATTR_IFINDEX;
278uint32_t idiagnl_msg_get_expires(
const struct idiagnl_msg *msg)
280 return msg->idiag_expires;
283void idiagnl_msg_set_expires(
struct idiagnl_msg *msg, uint32_t expires)
285 msg->idiag_expires = expires;
286 msg->ce_mask |= IDIAGNL_ATTR_EXPIRES;
289uint32_t idiagnl_msg_get_rqueue(
const struct idiagnl_msg *msg)
291 return msg->idiag_rqueue;
294void idiagnl_msg_set_rqueue(
struct idiagnl_msg *msg, uint32_t rqueue)
296 msg->idiag_rqueue = rqueue;
297 msg->ce_mask |= IDIAGNL_ATTR_RQUEUE;
300uint32_t idiagnl_msg_get_wqueue(
const struct idiagnl_msg *msg)
302 return msg->idiag_wqueue;
305void idiagnl_msg_set_wqueue(
struct idiagnl_msg *msg, uint32_t wqueue)
307 msg->idiag_wqueue = wqueue;
308 msg->ce_mask |= IDIAGNL_ATTR_WQUEUE;
311uint32_t idiagnl_msg_get_uid(
const struct idiagnl_msg *msg)
313 return msg->idiag_uid;
316void idiagnl_msg_set_uid(
struct idiagnl_msg *msg, uint32_t uid)
318 msg->idiag_uid = uid;
319 msg->ce_mask |= IDIAGNL_ATTR_UID;
322uint32_t idiagnl_msg_get_inode(
const struct idiagnl_msg *msg)
324 return msg->idiag_inode;
327void idiagnl_msg_set_inode(
struct idiagnl_msg *msg, uint32_t inode)
329 msg->idiag_inode = inode;
330 msg->ce_mask |= IDIAGNL_ATTR_INODE;
333uint8_t idiagnl_msg_get_tos(
const struct idiagnl_msg *msg)
335 return msg->idiag_tos;
338void idiagnl_msg_set_tos(
struct idiagnl_msg *msg, uint8_t tos)
340 msg->idiag_tos = tos;
341 msg->ce_mask |= IDIAGNL_ATTR_TOS;
344uint8_t idiagnl_msg_get_tclass(
const struct idiagnl_msg *msg)
346 return msg->idiag_tclass;
349void idiagnl_msg_set_tclass(
struct idiagnl_msg *msg, uint8_t tclass)
351 msg->idiag_tclass = tclass;
352 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
355uint8_t idiagnl_msg_get_shutdown(
const struct idiagnl_msg *msg)
357 return msg->idiag_shutdown;
360void idiagnl_msg_set_shutdown(
struct idiagnl_msg *msg, uint8_t shutdown)
362 msg->idiag_shutdown = shutdown;
363 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
366char *idiagnl_msg_get_cong(
const struct idiagnl_msg *msg)
368 return msg->idiag_cong;
371void idiagnl_msg_set_cong(
struct idiagnl_msg *msg,
char *cong)
373 free (msg->idiag_cong);
374 msg->idiag_cong = strdup(cong);
375 msg->ce_mask |= IDIAGNL_ATTR_CONG;
378struct idiagnl_meminfo *idiagnl_msg_get_meminfo(
const struct idiagnl_msg *msg)
380 return msg->idiag_meminfo;
383void idiagnl_msg_set_meminfo(
struct idiagnl_msg *msg,
struct idiagnl_meminfo *minfo)
385 if (msg->idiag_meminfo)
386 idiagnl_meminfo_put(msg->idiag_meminfo);
388 idiagnl_meminfo_get(minfo);
389 msg->idiag_meminfo = minfo;
390 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
393struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(
const struct idiagnl_msg *msg)
395 return msg->idiag_vegasinfo;
398void idiagnl_msg_set_vegasinfo(
struct idiagnl_msg *msg,
struct idiagnl_vegasinfo *vinfo)
400 if (msg->idiag_vegasinfo)
401 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
403 idiagnl_vegasinfo_get(vinfo);
404 msg->idiag_vegasinfo = vinfo;
405 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
408struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
410 return msg->idiag_tcpinfo;
413void idiagnl_msg_set_tcpinfo(
struct idiagnl_msg *msg,
struct tcp_info *tinfo)
415 memcpy(&msg->idiag_tcpinfo, tinfo,
sizeof(
struct tcp_info));
416 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
421static void idiag_msg_dump_line(
struct nl_object *a,
struct nl_dump_params *p)
423 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
424 char buf[64] = { 0 };
426 nl_dump_line(p,
"family: %s ", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
428 ntohs(msg->idiag_sport));
430 ntohs(msg->idiag_dport));
431 nl_dump(p,
"iif: %d ", msg->idiag_ifindex);
435static void idiag_msg_dump_details(
struct nl_object *a,
struct nl_dump_params *p)
437 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
438 char buf[64], buf2[64];
440 nl_dump(p,
"\nfamily: %s\n", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
443 nl_dump(p,
"timer (%s, %s, retransmits: %d)\n",
445 nl_msec2str(msg->idiag_expires, buf2,
sizeof(buf2)),
449 ntohs(msg->idiag_sport));
451 ntohs(msg->idiag_dport));
453 nl_dump(p,
"ifindex: %d\n", msg->idiag_ifindex);
454 nl_dump(p,
"rqueue: %-6d wqueue: %-6d\n", msg->idiag_rqueue, msg->idiag_wqueue);
455 nl_dump(p,
"uid %d\n", msg->idiag_uid);
456 nl_dump(p,
"inode %d\n", msg->idiag_inode);
457 if (msg->idiag_shutdown) {
458 nl_dump(p,
"socket shutdown: %s\n",
463 nl_dump(p,
"tos: 0x%x\n", msg->idiag_tos);
464 nl_dump(p,
"traffic class: %d\n", msg->idiag_tclass);
465 nl_dump(p,
"congestion algorithm: %s\n", msg->idiag_cong ? msg->idiag_cong :
"");
468static void idiag_msg_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
470 struct idiagnl_msg *msg = (
struct idiagnl_msg *) obj;
473 idiag_msg_dump_details(obj, p);
476 nl_dump(p,
"\tsocket state: %s\n",
479 nl_dump(p,
"\ttcp state: %s\n",
482 nl_dump(p,
"\tretransmits: %d\n",
483 msg->idiag_tcpinfo.tcpi_retransmits);
485 msg->idiag_tcpinfo.tcpi_probes);
487 msg->idiag_tcpinfo.tcpi_backoff);
491 nl_dump(p,
"\tsnd_wscale: %d\n", msg->idiag_tcpinfo.tcpi_snd_wscale);
492 nl_dump(p,
"\trcv_wscale: %d\n", msg->idiag_tcpinfo.tcpi_rcv_wscale);
493 nl_dump(p,
"\trto: %d\n", msg->idiag_tcpinfo.tcpi_rto);
494 nl_dump(p,
"\tato: %d\n", msg->idiag_tcpinfo.tcpi_ato);
499 nl_dump(p,
"\tunacked: %d\n", msg->idiag_tcpinfo.tcpi_unacked);
500 nl_dump(p,
"\tsacked: %d\n", msg->idiag_tcpinfo.tcpi_sacked);
502 nl_dump(p,
"\tlost: %d\n", msg->idiag_tcpinfo.tcpi_lost);
503 nl_dump(p,
"\tretransmit segments: %d\n",
504 msg->idiag_tcpinfo.tcpi_retrans);
506 msg->idiag_tcpinfo.tcpi_fackets);
507 nl_dump(p,
"\tlast data sent: %s\n",
508 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_sent, buf,
510 nl_dump(p,
"\tlast ack sent: %s\n",
511 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_sent, buf,
sizeof(buf)));
512 nl_dump(p,
"\tlast data recv: %s\n",
513 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_recv, buf,
515 nl_dump(p,
"\tlast ack recv: %s\n",
516 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_recv, buf,
521 nl_dump(p,
"\trcv ss threshold: %d\n",
522 msg->idiag_tcpinfo.tcpi_rcv_ssthresh);
523 nl_dump(p,
"\tsmoothed round trip time: %d\n",
524 msg->idiag_tcpinfo.tcpi_rtt);
525 nl_dump(p,
"\tround trip time variation: %d\n",
526 msg->idiag_tcpinfo.tcpi_rttvar);
527 nl_dump(p,
"\tsnd ss threshold: %s\n",
528 nl_size2str(msg->idiag_tcpinfo.tcpi_snd_ssthresh, buf,
530 nl_dump(p,
"\tsend congestion window: %d\n",
531 msg->idiag_tcpinfo.tcpi_snd_cwnd);
532 nl_dump(p,
"\tadvertised mss: %s\n",
535 nl_dump(p,
"\treordering: %d\n",
536 msg->idiag_tcpinfo.tcpi_reordering);
537 nl_dump(p,
"\trcv rround trip time: %d\n",
538 msg->idiag_tcpinfo.tcpi_rcv_rtt);
539 nl_dump(p,
"\treceive queue space: %s\n",
540 nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_space, buf,
542 nl_dump(p,
"\ttotal retransmits: %d\n",
543 msg->idiag_tcpinfo.tcpi_total_retrans);
546 if (msg->idiag_meminfo) {
567 if (msg->idiag_vegasinfo) {
569 nl_dump(p,
"\tvegas enabled: %d\n",
570 msg->idiag_vegasinfo->tcpv_enabled);
571 if (msg->idiag_vegasinfo->tcpv_enabled) {
573 msg->idiag_vegasinfo->tcpv_rttcnt);
574 nl_dump(p,
"\trtt (propagation delay): %d",
575 msg->idiag_vegasinfo->tcpv_rtt);
577 msg->idiag_vegasinfo->tcpv_minrtt);
582 if (msg->ce_mask & IDIAGNL_ATTR_MEMINFO) {
584 nl_dump(p,
"\trmem alloc: %d\n",
585 msg->idiag_skmeminfo[SK_MEMINFO_RMEM_ALLOC]);
587 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_RCVBUF],
589 nl_dump(p,
"\twmem alloc: %d\n",
590 msg->idiag_skmeminfo[SK_MEMINFO_WMEM_ALLOC]);
592 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_SNDBUF],
594 nl_dump(p,
"\tfwd alloc: %d\n",
595 msg->idiag_skmeminfo[SK_MEMINFO_FWD_ALLOC]);
596 nl_dump(p,
"\twmem queued: %s\n",
597 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_WMEM_QUEUED],
600 msg->idiag_skmeminfo[SK_MEMINFO_OPTMEM]);
602 msg->idiag_skmeminfo[SK_MEMINFO_BACKLOG]);
607static void idiagnl_msg_free(
struct nl_object *a)
609 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
613 free(msg->idiag_cong);
616 idiagnl_meminfo_put(msg->idiag_meminfo);
617 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
620static int idiagnl_msg_clone(
struct nl_object *_dst,
struct nl_object *_src)
622 struct idiagnl_msg *dst = (
struct idiagnl_msg *) _dst;
623 struct idiagnl_msg *src = (
struct idiagnl_msg *) _src;
625 dst->idiag_src = NULL;
626 dst->idiag_dst = NULL;
627 dst->idiag_cong = NULL;
628 dst->idiag_meminfo = NULL;
629 dst->idiag_vegasinfo = NULL;
630 dst->ce_mask &= ~(IDIAGNL_ATTR_CONG |
633 IDIAGNL_ATTR_MEMINFO |
634 IDIAGNL_ATTR_VEGASINFO);
636 if (src->idiag_cong) {
637 if (!(dst->idiag_cong = strdup(src->idiag_cong)))
639 dst->ce_mask |= IDIAGNL_ATTR_CONG;
642 if (src->idiag_src) {
645 dst->ce_mask |= IDIAGNL_ATTR_SRC;
648 if (src->idiag_dst) {
651 dst->ce_mask |= IDIAGNL_ATTR_DST;
654 if (src->idiag_meminfo) {
655 if (!(dst->idiag_meminfo = (
struct idiagnl_meminfo *)
nl_object_clone((
struct nl_object *) src->idiag_meminfo)))
657 dst->ce_mask |= IDIAGNL_ATTR_MEMINFO;
660 if (src->idiag_vegasinfo) {
661 if (!(dst->idiag_vegasinfo = (
struct idiagnl_vegasinfo *)
nl_object_clone((
struct nl_object *) src->idiag_vegasinfo)))
663 dst->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
669static struct nla_policy ext_policy[INET_DIAG_MAX+1] = {
670 [INET_DIAG_MEMINFO] = { .
minlen =
sizeof(
struct inet_diag_meminfo) },
671 [INET_DIAG_INFO] = { .minlen =
sizeof(
struct tcp_info) },
672 [INET_DIAG_VEGASINFO] = { .minlen =
sizeof(
struct tcpvegas_info) },
674 [INET_DIAG_TOS] = { .type =
NLA_U8 },
675 [INET_DIAG_TCLASS] = { .type =
NLA_U8 },
677 [INET_DIAG_SKMEMINFO] = { .minlen = (
sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) },
678 [INET_DIAG_SHUTDOWN] = { .type =
NLA_U8 },
681int idiagnl_msg_parse(
struct nlmsghdr *nlh,
struct idiagnl_msg **result)
683 struct idiagnl_msg *msg = NULL;
684 struct inet_diag_msg *raw_msg = NULL;
685 struct nl_addr *src = NULL, *dst = NULL;
686 struct nlattr *tb[INET_DIAG_MAX+1];
689 msg = idiagnl_msg_alloc();
693 err =
nlmsg_parse(nlh,
sizeof(
struct inet_diag_msg), tb, INET_DIAG_MAX,
699 msg->idiag_family = raw_msg->idiag_family;
700 msg->idiag_state = raw_msg->idiag_state;
701 msg->idiag_timer = raw_msg->idiag_timer;
702 msg->idiag_retrans = raw_msg->idiag_retrans;
703 msg->idiag_expires = raw_msg->idiag_expires;
704 msg->idiag_rqueue = raw_msg->idiag_rqueue;
705 msg->idiag_wqueue = raw_msg->idiag_wqueue;
706 msg->idiag_uid = raw_msg->idiag_uid;
707 msg->idiag_inode = raw_msg->idiag_inode;
708 msg->idiag_sport = raw_msg->id.idiag_sport;
709 msg->idiag_dport = raw_msg->id.idiag_dport;
710 msg->idiag_ifindex = raw_msg->id.idiag_if;
712 msg->ce_mask = (IDIAGNL_ATTR_FAMILY |
715 IDIAGNL_ATTR_RETRANS |
716 IDIAGNL_ATTR_EXPIRES |
717 IDIAGNL_ATTR_RQUEUE |
718 IDIAGNL_ATTR_WQUEUE |
723 IDIAGNL_ATTR_IFINDEX);
725 dst =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
726 sizeof(raw_msg->id.idiag_dst));
730 err = idiagnl_msg_set_dst(msg, dst);
736 src =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src,
737 sizeof(raw_msg->id.idiag_src));
741 err = idiagnl_msg_set_src(msg, src);
747 if (tb[INET_DIAG_TOS]) {
748 msg->idiag_tos =
nla_get_u8(tb[INET_DIAG_TOS]);
749 msg->ce_mask |= IDIAGNL_ATTR_TOS;
752 if (tb[INET_DIAG_TCLASS]) {
753 msg->idiag_tclass =
nla_get_u8(tb[INET_DIAG_TCLASS]);
754 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
757 if (tb[INET_DIAG_SHUTDOWN]) {
758 msg->idiag_shutdown =
nla_get_u8(tb[INET_DIAG_SHUTDOWN]);
759 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
762 if (tb[INET_DIAG_CONG]) {
763 msg->idiag_cong = nla_strdup(tb[INET_DIAG_CONG]);
764 msg->ce_mask |= IDIAGNL_ATTR_CONG;
767 if (tb[INET_DIAG_INFO]) {
768 nla_memcpy(&msg->idiag_tcpinfo, tb[INET_DIAG_INFO],
769 sizeof(msg->idiag_tcpinfo));
770 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
773 if (tb[INET_DIAG_MEMINFO]) {
774 struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc();
775 struct inet_diag_meminfo *raw_minfo = NULL;
780 raw_minfo = (
struct inet_diag_meminfo *)
783 idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem);
784 idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem);
785 idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem);
786 idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem);
788 msg->idiag_meminfo = minfo;
789 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
792 if (tb[INET_DIAG_VEGASINFO]) {
793 struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc();
794 struct tcpvegas_info *raw_vinfo = NULL;
799 raw_vinfo = (
struct tcpvegas_info *)
802 idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled);
803 idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt);
804 idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt);
805 idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt);
807 msg->idiag_vegasinfo = vinfo;
808 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
811 if (tb[INET_DIAG_SKMEMINFO]) {
812 nla_memcpy(&msg->idiag_skmeminfo, tb[INET_DIAG_SKMEMINFO],
813 sizeof(msg->idiag_skmeminfo));
814 msg->ce_mask |= IDIAGNL_ATTR_SKMEMINFO;
821 idiagnl_msg_put(msg);
829static const struct trans_tbl idiagnl_attrs[] = {
830 __ADD(IDIAGNL_ATTR_FAMILY, family),
831 __ADD(IDIAGNL_ATTR_STATE, state),
832 __ADD(IDIAGNL_ATTR_TIMER, timer),
833 __ADD(IDIAGNL_ATTR_RETRANS, retrans),
834 __ADD(IDIAGNL_ATTR_SPORT, sport),
835 __ADD(IDIAGNL_ATTR_DPORT, dport),
836 __ADD(IDIAGNL_ATTR_SRC, src),
837 __ADD(IDIAGNL_ATTR_DST, dst),
838 __ADD(IDIAGNL_ATTR_IFINDEX, ifindex),
839 __ADD(IDIAGNL_ATTR_EXPIRES, expires),
840 __ADD(IDIAGNL_ATTR_RQUEUE, rqueue),
841 __ADD(IDIAGNL_ATTR_WQUEUE, wqueue),
842 __ADD(IDIAGNL_ATTR_UID, uid),
843 __ADD(IDIAGNL_ATTR_INODE, inode),
844 __ADD(IDIAGNL_ATTR_TOS, tos),
845 __ADD(IDIAGNL_ATTR_TCLASS, tclass),
846 __ADD(IDIAGNL_ATTR_SHUTDOWN, shutdown),
847 __ADD(IDIAGNL_ATTR_CONG, cong),
848 __ADD(IDIAGNL_ATTR_MEMINFO, meminfo),
849 __ADD(IDIAGNL_ATTR_VEGASINFO, vegasinfo),
850 __ADD(IDIAGNL_ATTR_TCPINFO, tcpinfo),
851 __ADD(IDIAGNL_ATTR_SKMEMINFO, skmeminfo),
854static char *_idiagnl_attrs2str(
int attrs,
char *buf,
size_t len)
856 return __flags2str(attrs, buf, len, idiagnl_attrs,
857 ARRAY_SIZE(idiagnl_attrs));
860static uint64_t idiagnl_compare(
struct nl_object *_a,
struct nl_object *_b,
861 uint64_t attrs,
int flags)
863 struct idiagnl_msg *a = (
struct idiagnl_msg *) _a;
864 struct idiagnl_msg *b = (
struct idiagnl_msg *) _b;
867#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, IDIAGNL_ATTR_##ATTR, a, b, EXPR)
868 diff |= _DIFF(FAMILY, a->idiag_family != b->idiag_family);
869 diff |= _DIFF(STATE, a->idiag_state != b->idiag_state);
870 diff |= _DIFF(TIMER, a->idiag_timer != b->idiag_timer);
871 diff |= _DIFF(RETRANS, a->idiag_retrans != b->idiag_retrans);
872 diff |= _DIFF(SPORT, a->idiag_sport != b->idiag_sport);
873 diff |= _DIFF(DPORT, a->idiag_dport != b->idiag_dport);
874 diff |= _DIFF(SRC,
nl_addr_cmp (a->idiag_src, b->idiag_src));
875 diff |= _DIFF(DST,
nl_addr_cmp (a->idiag_dst, b->idiag_dst));
876 diff |= _DIFF(IFINDEX, a->idiag_ifindex != b->idiag_ifindex);
877 diff |= _DIFF(EXPIRES, a->idiag_expires != b->idiag_expires);
878 diff |= _DIFF(RQUEUE, a->idiag_rqueue != b->idiag_rqueue);
879 diff |= _DIFF(WQUEUE, a->idiag_wqueue != b->idiag_wqueue);
880 diff |= _DIFF(UID, a->idiag_uid != b->idiag_uid);
881 diff |= _DIFF(INODE, a->idiag_inode != b->idiag_inode);
882 diff |= _DIFF(TOS, a->idiag_tos != b->idiag_tos);
883 diff |= _DIFF(TCLASS, a->idiag_tclass != b->idiag_tclass);
884 diff |= _DIFF(SHUTDOWN, a->idiag_shutdown != b->idiag_shutdown);
885 diff |= _DIFF(CONG, strcmp(a->idiag_cong, b->idiag_cong));
886 diff |= _DIFF(MEMINFO,
nl_object_diff((
struct nl_object *) a->idiag_meminfo, (
struct nl_object *) b->idiag_meminfo));
887 diff |= _DIFF(VEGASINFO,
nl_object_diff((
struct nl_object *) a->idiag_vegasinfo, (
struct nl_object *) b->idiag_vegasinfo));
888 diff |= _DIFF(TCPINFO, memcmp(&a->idiag_tcpinfo, &b->idiag_tcpinfo,
sizeof(a->idiag_tcpinfo)));
889 diff |= _DIFF(SKMEMINFO, memcmp(a->idiag_skmeminfo, b->idiag_skmeminfo,
sizeof(a->idiag_skmeminfo)));
894static void idiagnl_keygen(
struct nl_object *obj, uint32_t *hashkey,
897 struct idiagnl_msg *msg = (
struct idiagnl_msg *)obj;
899 struct idiagnl_hash_key {
905 } __attribute__((packed)) key;
907 key_sz =
sizeof(key);
908 key.family = msg->idiag_family;
911 key.sport = msg->idiag_sport;
912 key.dport = msg->idiag_dport;
914 if (msg->idiag_src) {
918 if (msg->idiag_dst) {
923 *hashkey = nl_hash(&key, key_sz, 0) % table_sz;
925 NL_DBG(5,
"idiagnl %p key (fam %d src_hash %d dst_hash %d sport %d dport %d) keysz %d, hash 0x%x\n",
926 msg, key.family, key.src_hash, key.dst_hash, key.sport, key.dport, key_sz, *hashkey);
932struct nl_object_ops idiagnl_msg_obj_ops = {
933 .oo_name =
"idiag/idiag_msg",
934 .oo_size =
sizeof(
struct idiagnl_msg),
935 .oo_free_data = idiagnl_msg_free,
936 .oo_clone = idiagnl_msg_clone,
942 .oo_compare = idiagnl_compare,
943 .oo_keygen = idiagnl_keygen,
944 .oo_attrs2str = _idiagnl_attrs2str,
945 .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.