12 #include <netlink-private/netlink.h>
13 #include <netlink/hashtable.h>
14 #include <netlink/idiag/msg.h>
15 #include <netlink/idiag/meminfo.h>
16 #include <netlink/idiag/vegasinfo.h>
17 #include <linux/inet_diag.h>
21 #define IDIAGNL_ATTR_FAMILY (0x1 << 1)
22 #define IDIAGNL_ATTR_STATE (0x1 << 2)
23 #define IDIAGNL_ATTR_TIMER (0x1 << 3)
24 #define IDIAGNL_ATTR_RETRANS (0x1 << 4)
25 #define IDIAGNL_ATTR_SPORT (0x1 << 5)
26 #define IDIAGNL_ATTR_DPORT (0x1 << 6)
27 #define IDIAGNL_ATTR_SRC (0x1 << 7)
28 #define IDIAGNL_ATTR_DST (0x1 << 8)
29 #define IDIAGNL_ATTR_IFINDEX (0x1 << 9)
30 #define IDIAGNL_ATTR_EXPIRES (0x1 << 10)
31 #define IDIAGNL_ATTR_RQUEUE (0x1 << 11)
32 #define IDIAGNL_ATTR_WQUEUE (0x1 << 12)
33 #define IDIAGNL_ATTR_UID (0x1 << 13)
34 #define IDIAGNL_ATTR_INODE (0x1 << 14)
35 #define IDIAGNL_ATTR_TOS (0x1 << 15)
36 #define IDIAGNL_ATTR_TCLASS (0x1 << 16)
37 #define IDIAGNL_ATTR_SHUTDOWN (0x1 << 17)
38 #define IDIAGNL_ATTR_CONG (0x1 << 18)
39 #define IDIAGNL_ATTR_MEMINFO (0x1 << 19)
40 #define IDIAGNL_ATTR_VEGASINFO (0x1 << 20)
41 #define IDIAGNL_ATTR_TCPINFO (0x1 << 21)
42 #define IDIAGNL_ATTR_SKMEMINFO (0x1 << 22)
44 #define _INET_DIAG_ALL ((1<<(INET_DIAG_MAX+1))-1)
55 struct idiagnl_msg *idiagnl_msg_alloc(
void)
60 void idiagnl_msg_get(
struct idiagnl_msg *msg)
65 void idiagnl_msg_put(
struct idiagnl_msg *msg)
70 static struct nl_cache_ops idiagnl_msg_ops;
72 static int idiagnl_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
73 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
75 struct idiagnl_msg *msg = NULL;
78 if ((err = idiagnl_msg_parse(nlh, &msg)) < 0)
81 err = pp->pp_cb((
struct nl_object *) msg, pp);
87 static int idiagnl_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
89 int family = cache->c_iarg1;
90 int states = cache->c_iarg2;
95 static struct nl_cache_ops idiagnl_msg_ops = {
96 .co_name =
"idiag/idiag",
97 .co_hdrsize =
sizeof(
struct inet_diag_msg),
99 { TCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
100 { DCCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
101 END_OF_MSGTYPES_LIST,
103 .co_protocol = NETLINK_INET_DIAG,
104 .co_request_update = idiagnl_request_update,
105 .co_msg_parser = idiagnl_msg_parser,
106 .co_obj_ops = &idiagnl_msg_obj_ops,
109 static void __init idiagnl_init(
void)
114 static void __exit idiagnl_exit(
void)
136 struct nl_cache **result)
138 struct nl_cache *cache = NULL;
144 cache->c_iarg1 = family;
145 cache->c_iarg2 = states;
163 uint8_t idiagnl_msg_get_family(
const struct idiagnl_msg *msg)
165 return msg->idiag_family;
168 void idiagnl_msg_set_family(
struct idiagnl_msg *msg, uint8_t family)
170 msg->idiag_family = family;
171 msg->ce_mask |= IDIAGNL_ATTR_FAMILY;
174 uint8_t idiagnl_msg_get_state(
const struct idiagnl_msg *msg)
176 return msg->idiag_state;
179 void idiagnl_msg_set_state(
struct idiagnl_msg *msg, uint8_t state)
181 msg->idiag_state = state;
182 msg->ce_mask |= IDIAGNL_ATTR_STATE;
185 uint8_t idiagnl_msg_get_timer(
const struct idiagnl_msg *msg)
187 return msg->idiag_timer;
190 void idiagnl_msg_set_timer(
struct idiagnl_msg *msg, uint8_t timer)
192 msg->idiag_timer = timer;
193 msg->ce_mask |= IDIAGNL_ATTR_TIMER;
196 uint8_t idiagnl_msg_get_retrans(
const struct idiagnl_msg *msg)
198 return msg->idiag_retrans;
201 void idiagnl_msg_set_retrans(
struct idiagnl_msg *msg, uint8_t retrans)
203 msg->idiag_retrans = retrans;
204 msg->ce_mask |= IDIAGNL_ATTR_RETRANS;
207 uint16_t idiagnl_msg_get_sport(
struct idiagnl_msg *msg)
209 return msg->idiag_sport;
212 void idiagnl_msg_set_sport(
struct idiagnl_msg *msg, uint16_t port)
214 msg->idiag_sport = port;
215 msg->ce_mask |= IDIAGNL_ATTR_SPORT;
218 uint16_t idiagnl_msg_get_dport(
struct idiagnl_msg *msg)
220 return msg->idiag_dport;
223 void idiagnl_msg_set_dport(
struct idiagnl_msg *msg, uint16_t port)
225 msg->idiag_dport = port;
226 msg->ce_mask |= IDIAGNL_ATTR_DPORT;
229 struct nl_addr *idiagnl_msg_get_src(
const struct idiagnl_msg *msg)
231 return msg->idiag_src;
234 int idiagnl_msg_set_src(
struct idiagnl_msg *msg,
struct nl_addr *addr)
240 msg->idiag_src = addr;
241 msg->ce_mask |= IDIAGNL_ATTR_SRC;
246 struct nl_addr *idiagnl_msg_get_dst(
const struct idiagnl_msg *msg)
248 return msg->idiag_dst;
251 int idiagnl_msg_set_dst(
struct idiagnl_msg *msg,
struct nl_addr *addr)
257 msg->idiag_dst = addr;
258 msg->ce_mask |= IDIAGNL_ATTR_DST;
263 uint32_t idiagnl_msg_get_ifindex(
const struct idiagnl_msg *msg)
265 return msg->idiag_ifindex;
268 void idiagnl_msg_set_ifindex(
struct idiagnl_msg *msg, uint32_t ifindex)
270 msg->idiag_ifindex = ifindex;
271 msg->ce_mask |= IDIAGNL_ATTR_IFINDEX;
274 uint32_t idiagnl_msg_get_expires(
const struct idiagnl_msg *msg)
276 return msg->idiag_expires;
279 void idiagnl_msg_set_expires(
struct idiagnl_msg *msg, uint32_t expires)
281 msg->idiag_expires = expires;
282 msg->ce_mask |= IDIAGNL_ATTR_EXPIRES;
285 uint32_t idiagnl_msg_get_rqueue(
const struct idiagnl_msg *msg)
287 return msg->idiag_rqueue;
290 void idiagnl_msg_set_rqueue(
struct idiagnl_msg *msg, uint32_t rqueue)
292 msg->idiag_rqueue = rqueue;
293 msg->ce_mask |= IDIAGNL_ATTR_RQUEUE;
296 uint32_t idiagnl_msg_get_wqueue(
const struct idiagnl_msg *msg)
298 return msg->idiag_wqueue;
301 void idiagnl_msg_set_wqueue(
struct idiagnl_msg *msg, uint32_t wqueue)
303 msg->idiag_wqueue = wqueue;
304 msg->ce_mask |= IDIAGNL_ATTR_WQUEUE;
307 uint32_t idiagnl_msg_get_uid(
const struct idiagnl_msg *msg)
309 return msg->idiag_uid;
312 void idiagnl_msg_set_uid(
struct idiagnl_msg *msg, uint32_t uid)
314 msg->idiag_uid = uid;
315 msg->ce_mask |= IDIAGNL_ATTR_UID;
318 uint32_t idiagnl_msg_get_inode(
const struct idiagnl_msg *msg)
320 return msg->idiag_inode;
323 void idiagnl_msg_set_inode(
struct idiagnl_msg *msg, uint32_t inode)
325 msg->idiag_inode = inode;
326 msg->ce_mask |= IDIAGNL_ATTR_INODE;
329 uint8_t idiagnl_msg_get_tos(
const struct idiagnl_msg *msg)
331 return msg->idiag_tos;
334 void idiagnl_msg_set_tos(
struct idiagnl_msg *msg, uint8_t tos)
336 msg->idiag_tos = tos;
337 msg->ce_mask |= IDIAGNL_ATTR_TOS;
340 uint8_t idiagnl_msg_get_tclass(
const struct idiagnl_msg *msg)
342 return msg->idiag_tclass;
345 void idiagnl_msg_set_tclass(
struct idiagnl_msg *msg, uint8_t tclass)
347 msg->idiag_tclass = tclass;
348 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
351 uint8_t idiagnl_msg_get_shutdown(
const struct idiagnl_msg *msg)
353 return msg->idiag_shutdown;
356 void idiagnl_msg_set_shutdown(
struct idiagnl_msg *msg, uint8_t shutdown)
358 msg->idiag_shutdown = shutdown;
359 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
362 char *idiagnl_msg_get_cong(
const struct idiagnl_msg *msg)
364 return msg->idiag_cong;
367 void idiagnl_msg_set_cong(
struct idiagnl_msg *msg,
char *cong)
369 free (msg->idiag_cong);
370 msg->idiag_cong = strdup(cong);
371 msg->ce_mask |= IDIAGNL_ATTR_CONG;
374 struct idiagnl_meminfo *idiagnl_msg_get_meminfo(
const struct idiagnl_msg *msg)
376 return msg->idiag_meminfo;
379 void idiagnl_msg_set_meminfo(
struct idiagnl_msg *msg,
struct idiagnl_meminfo *minfo)
381 if (msg->idiag_meminfo)
382 idiagnl_meminfo_put(msg->idiag_meminfo);
384 idiagnl_meminfo_get(minfo);
385 msg->idiag_meminfo = minfo;
386 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
389 struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(
const struct idiagnl_msg *msg)
391 return msg->idiag_vegasinfo;
394 void idiagnl_msg_set_vegasinfo(
struct idiagnl_msg *msg,
struct idiagnl_vegasinfo *vinfo)
396 if (msg->idiag_vegasinfo)
397 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
399 idiagnl_vegasinfo_get(vinfo);
400 msg->idiag_vegasinfo = vinfo;
401 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
404 struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
406 return msg->idiag_tcpinfo;
409 void idiagnl_msg_set_tcpinfo(
struct idiagnl_msg *msg,
struct tcp_info *tinfo)
411 memcpy(&msg->idiag_tcpinfo, tinfo,
sizeof(
struct tcp_info));
412 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
417 static void idiag_msg_dump_line(
struct nl_object *a,
struct nl_dump_params *p)
419 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
420 char buf[64] = { 0 };
422 nl_dump_line(p,
"family: %s ", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
424 ntohs(msg->idiag_sport));
426 ntohs(msg->idiag_dport));
427 nl_dump(p,
"iif: %d ", msg->idiag_ifindex);
431 static void idiag_msg_dump_details(
struct nl_object *a,
struct nl_dump_params *p)
433 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
434 char buf[64], buf2[64];
436 nl_dump(p,
"\nfamily: %s\n", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
439 nl_dump(p,
"timer (%s, %s, retransmits: %d)\n",
441 nl_msec2str(msg->idiag_expires, buf2,
sizeof(buf2)),
445 ntohs(msg->idiag_sport));
447 ntohs(msg->idiag_dport));
449 nl_dump(p,
"ifindex: %d\n", msg->idiag_ifindex);
450 nl_dump(p,
"rqueue: %-6d wqueue: %-6d\n", msg->idiag_rqueue, msg->idiag_wqueue);
451 nl_dump(p,
"uid %d\n", msg->idiag_uid);
452 nl_dump(p,
"inode %d\n", msg->idiag_inode);
453 if (msg->idiag_shutdown) {
454 nl_dump(p,
"socket shutdown: %s\n",
459 nl_dump(p,
"tos: 0x%x\n", msg->idiag_tos);
460 nl_dump(p,
"traffic class: %d\n", msg->idiag_tclass);
461 nl_dump(p,
"congestion algorithm: %s\n", msg->idiag_cong ? :
"");
464 static void idiag_msg_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
466 struct idiagnl_msg *msg = (
struct idiagnl_msg *) obj;
469 idiag_msg_dump_details(obj, p);
472 nl_dump(p,
"\tsocket state: %s\n",
475 nl_dump(p,
"\ttcp state: %s\n",
478 nl_dump(p,
"\tretransmits: %d\n",
479 msg->idiag_tcpinfo.tcpi_retransmits);
481 msg->idiag_tcpinfo.tcpi_probes);
483 msg->idiag_tcpinfo.tcpi_backoff);
487 nl_dump(p,
"\tsnd_wscale: %d\n", msg->idiag_tcpinfo.tcpi_snd_wscale);
488 nl_dump(p,
"\trcv_wscale: %d\n", msg->idiag_tcpinfo.tcpi_rcv_wscale);
489 nl_dump(p,
"\trto: %d\n", msg->idiag_tcpinfo.tcpi_rto);
490 nl_dump(p,
"\tato: %d\n", msg->idiag_tcpinfo.tcpi_ato);
495 nl_dump(p,
"\tunacked: %d\n", msg->idiag_tcpinfo.tcpi_unacked);
496 nl_dump(p,
"\tsacked: %d\n", msg->idiag_tcpinfo.tcpi_sacked);
498 nl_dump(p,
"\tlost: %d\n", msg->idiag_tcpinfo.tcpi_lost);
499 nl_dump(p,
"\tretransmit segments: %d\n",
500 msg->idiag_tcpinfo.tcpi_retrans);
502 msg->idiag_tcpinfo.tcpi_fackets);
503 nl_dump(p,
"\tlast data sent: %s\n",
504 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_sent, buf,
506 nl_dump(p,
"\tlast ack sent: %s\n",
507 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_sent, buf,
sizeof(buf)));
508 nl_dump(p,
"\tlast data recv: %s\n",
509 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_recv, buf,
511 nl_dump(p,
"\tlast ack recv: %s\n",
512 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_recv, buf,
517 nl_dump(p,
"\trcv ss threshold: %d\n",
518 msg->idiag_tcpinfo.tcpi_rcv_ssthresh);
519 nl_dump(p,
"\tsmoothed round trip time: %d\n",
520 msg->idiag_tcpinfo.tcpi_rtt);
521 nl_dump(p,
"\tround trip time variation: %d\n",
522 msg->idiag_tcpinfo.tcpi_rttvar);
523 nl_dump(p,
"\tsnd ss threshold: %s\n",
524 nl_size2str(msg->idiag_tcpinfo.tcpi_snd_ssthresh, buf,
526 nl_dump(p,
"\tsend congestion window: %d\n",
527 msg->idiag_tcpinfo.tcpi_snd_cwnd);
528 nl_dump(p,
"\tadvertised mss: %s\n",
531 nl_dump(p,
"\treordering: %d\n",
532 msg->idiag_tcpinfo.tcpi_reordering);
533 nl_dump(p,
"\trcv rround trip time: %d\n",
534 msg->idiag_tcpinfo.tcpi_rcv_rtt);
535 nl_dump(p,
"\treceive queue space: %s\n",
536 nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_space, buf,
538 nl_dump(p,
"\ttotal retransmits: %d\n",
539 msg->idiag_tcpinfo.tcpi_total_retrans);
542 if (msg->idiag_meminfo) {
563 if (msg->idiag_vegasinfo) {
565 nl_dump(p,
"\tvegas enabled: %d\n",
566 msg->idiag_vegasinfo->tcpv_enabled);
567 if (msg->idiag_vegasinfo->tcpv_enabled) {
569 msg->idiag_vegasinfo->tcpv_rttcnt);
570 nl_dump(p,
"\trtt (propagation delay): %d",
571 msg->idiag_vegasinfo->tcpv_rtt);
573 msg->idiag_vegasinfo->tcpv_minrtt);
578 if (msg->ce_mask & IDIAGNL_ATTR_MEMINFO) {
580 nl_dump(p,
"\trmem alloc: %d\n",
581 msg->idiag_skmeminfo[SK_MEMINFO_RMEM_ALLOC]);
583 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_RCVBUF],
585 nl_dump(p,
"\twmem alloc: %d\n",
586 msg->idiag_skmeminfo[SK_MEMINFO_WMEM_ALLOC]);
588 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_SNDBUF],
590 nl_dump(p,
"\tfwd alloc: %d\n",
591 msg->idiag_skmeminfo[SK_MEMINFO_FWD_ALLOC]);
592 nl_dump(p,
"\twmem queued: %s\n",
593 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_WMEM_QUEUED],
596 msg->idiag_skmeminfo[SK_MEMINFO_OPTMEM]);
598 msg->idiag_skmeminfo[SK_MEMINFO_BACKLOG]);
603 static void idiagnl_msg_free(
struct nl_object *a)
605 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
609 free(msg->idiag_cong);
612 idiagnl_meminfo_put(msg->idiag_meminfo);
613 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
616 static int idiagnl_msg_clone(
struct nl_object *_dst,
struct nl_object *_src)
618 struct idiagnl_msg *dst = (
struct idiagnl_msg *) _dst;
619 struct idiagnl_msg *src = (
struct idiagnl_msg *) _src;
621 dst->idiag_cong = NULL;
622 dst->idiag_src = NULL;
623 dst->idiag_dst = NULL;
624 dst->idiag_meminfo = NULL;
625 dst->idiag_vegasinfo = NULL;
626 dst->ce_mask &= ~(IDIAGNL_ATTR_CONG |
629 IDIAGNL_ATTR_MEMINFO |
630 IDIAGNL_ATTR_VEGASINFO);
632 if (src->idiag_cong) {
633 if (!(dst->idiag_cong = strdup(src->idiag_cong)))
635 dst->ce_mask |= IDIAGNL_ATTR_CONG;
638 if (src->idiag_src) {
641 dst->ce_mask |= IDIAGNL_ATTR_SRC;
644 if (src->idiag_dst) {
647 dst->ce_mask |= IDIAGNL_ATTR_DST;
650 if (src->idiag_meminfo) {
651 if (!(dst->idiag_meminfo = (
struct idiagnl_meminfo *)
nl_object_clone((
struct nl_object *) src->idiag_meminfo)))
653 dst->ce_mask |= IDIAGNL_ATTR_MEMINFO;
656 if (src->idiag_vegasinfo) {
657 if (!(dst->idiag_vegasinfo = (
struct idiagnl_vegasinfo *)
nl_object_clone((
struct nl_object *) src->idiag_vegasinfo)))
659 dst->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
665 static struct nla_policy ext_policy[INET_DIAG_MAX+1] = {
666 [INET_DIAG_MEMINFO] = { .
minlen =
sizeof(
struct inet_diag_meminfo) },
667 [INET_DIAG_INFO] = { .minlen =
sizeof(
struct tcp_info) },
668 [INET_DIAG_VEGASINFO] = { .minlen =
sizeof(
struct tcpvegas_info) },
670 [INET_DIAG_TOS] = { .type =
NLA_U8 },
671 [INET_DIAG_TCLASS] = { .type =
NLA_U8 },
673 [INET_DIAG_SKMEMINFO] = { .minlen = (
sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) },
674 [INET_DIAG_SHUTDOWN] = { .type =
NLA_U8 },
677 int idiagnl_msg_parse(
struct nlmsghdr *nlh,
struct idiagnl_msg **result)
679 struct idiagnl_msg *msg = NULL;
680 struct inet_diag_msg *raw_msg = NULL;
681 struct nl_addr *src = NULL, *dst = NULL;
682 struct nlattr *tb[INET_DIAG_MAX+1];
685 msg = idiagnl_msg_alloc();
689 err =
nlmsg_parse(nlh,
sizeof(
struct inet_diag_msg), tb, INET_DIAG_MAX,
695 msg->idiag_family = raw_msg->idiag_family;
696 msg->idiag_state = raw_msg->idiag_state;
697 msg->idiag_timer = raw_msg->idiag_timer;
698 msg->idiag_retrans = raw_msg->idiag_retrans;
699 msg->idiag_expires = raw_msg->idiag_expires;
700 msg->idiag_rqueue = raw_msg->idiag_rqueue;
701 msg->idiag_wqueue = raw_msg->idiag_wqueue;
702 msg->idiag_uid = raw_msg->idiag_uid;
703 msg->idiag_inode = raw_msg->idiag_inode;
704 msg->idiag_sport = raw_msg->id.idiag_sport;
705 msg->idiag_dport = raw_msg->id.idiag_dport;
706 msg->idiag_ifindex = raw_msg->id.idiag_if;
708 msg->ce_mask = (IDIAGNL_ATTR_FAMILY |
711 IDIAGNL_ATTR_RETRANS |
712 IDIAGNL_ATTR_EXPIRES |
713 IDIAGNL_ATTR_RQUEUE |
714 IDIAGNL_ATTR_WQUEUE |
719 IDIAGNL_ATTR_IFINDEX);
721 dst =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
722 sizeof(raw_msg->id.idiag_dst));
726 err = idiagnl_msg_set_dst(msg, dst);
732 src =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src,
733 sizeof(raw_msg->id.idiag_src));
737 err = idiagnl_msg_set_src(msg, src);
743 if (tb[INET_DIAG_TOS]) {
744 msg->idiag_tos =
nla_get_u8(tb[INET_DIAG_TOS]);
745 msg->ce_mask |= IDIAGNL_ATTR_TOS;
748 if (tb[INET_DIAG_TCLASS]) {
749 msg->idiag_tclass =
nla_get_u8(tb[INET_DIAG_TCLASS]);
750 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
753 if (tb[INET_DIAG_SHUTDOWN]) {
754 msg->idiag_shutdown =
nla_get_u8(tb[INET_DIAG_SHUTDOWN]);
755 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
758 if (tb[INET_DIAG_CONG]) {
759 msg->idiag_cong = nla_strdup(tb[INET_DIAG_CONG]);
760 msg->ce_mask |= IDIAGNL_ATTR_CONG;
763 if (tb[INET_DIAG_INFO]) {
764 nla_memcpy(&msg->idiag_tcpinfo, tb[INET_DIAG_INFO],
765 sizeof(msg->idiag_tcpinfo));
766 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
769 if (tb[INET_DIAG_MEMINFO]) {
770 struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc();
771 struct inet_diag_meminfo *raw_minfo = NULL;
776 raw_minfo = (
struct inet_diag_meminfo *)
779 idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem);
780 idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem);
781 idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem);
782 idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem);
784 msg->idiag_meminfo = minfo;
785 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
788 if (tb[INET_DIAG_VEGASINFO]) {
789 struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc();
790 struct tcpvegas_info *raw_vinfo = NULL;
795 raw_vinfo = (
struct tcpvegas_info *)
798 idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled);
799 idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt);
800 idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt);
801 idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt);
803 msg->idiag_vegasinfo = vinfo;
804 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
807 if (tb[INET_DIAG_SKMEMINFO]) {
808 nla_memcpy(&msg->idiag_skmeminfo, tb[INET_DIAG_SKMEMINFO],
809 sizeof(msg->idiag_skmeminfo));
810 msg->ce_mask |= IDIAGNL_ATTR_SKMEMINFO;
817 idiagnl_msg_put(msg);
825 static const struct trans_tbl idiagnl_attrs[] = {
826 __ADD(IDIAGNL_ATTR_FAMILY, family),
827 __ADD(IDIAGNL_ATTR_STATE, state),
828 __ADD(IDIAGNL_ATTR_TIMER, timer),
829 __ADD(IDIAGNL_ATTR_RETRANS, retrans),
830 __ADD(IDIAGNL_ATTR_SPORT, sport),
831 __ADD(IDIAGNL_ATTR_DPORT, dport),
832 __ADD(IDIAGNL_ATTR_SRC, src),
833 __ADD(IDIAGNL_ATTR_DST, dst),
834 __ADD(IDIAGNL_ATTR_IFINDEX, ifindex),
835 __ADD(IDIAGNL_ATTR_EXPIRES, expires),
836 __ADD(IDIAGNL_ATTR_RQUEUE, rqueue),
837 __ADD(IDIAGNL_ATTR_WQUEUE, wqueue),
838 __ADD(IDIAGNL_ATTR_UID, uid),
839 __ADD(IDIAGNL_ATTR_INODE, inode),
840 __ADD(IDIAGNL_ATTR_TOS, tos),
841 __ADD(IDIAGNL_ATTR_TCLASS, tclass),
842 __ADD(IDIAGNL_ATTR_SHUTDOWN, shutdown),
843 __ADD(IDIAGNL_ATTR_CONG, cong),
844 __ADD(IDIAGNL_ATTR_MEMINFO, meminfo),
845 __ADD(IDIAGNL_ATTR_VEGASINFO, vegasinfo),
846 __ADD(IDIAGNL_ATTR_TCPINFO, tcpinfo),
847 __ADD(IDIAGNL_ATTR_SKMEMINFO, skmeminfo),
850 static char *_idiagnl_attrs2str(
int attrs,
char *buf,
size_t len)
852 return __flags2str(attrs, buf, len, idiagnl_attrs,
853 ARRAY_SIZE(idiagnl_attrs));
856 static int idiagnl_compare(
struct nl_object *_a,
struct nl_object *_b,
857 uint32_t attrs,
int flags)
859 struct idiagnl_msg *a = (
struct idiagnl_msg *) _a;
860 struct idiagnl_msg *b = (
struct idiagnl_msg *) _b;
863 #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, IDIAGNL_ATTR_##ATTR, a, b, EXPR)
864 diff |= _DIFF(FAMILY, a->idiag_family != b->idiag_family);
865 diff |= _DIFF(STATE, a->idiag_state != b->idiag_state);
866 diff |= _DIFF(TIMER, a->idiag_timer != b->idiag_timer);
867 diff |= _DIFF(RETRANS, a->idiag_retrans != b->idiag_retrans);
868 diff |= _DIFF(SPORT, a->idiag_sport != b->idiag_sport);
869 diff |= _DIFF(DPORT, a->idiag_dport != b->idiag_dport);
870 diff |= _DIFF(SRC,
nl_addr_cmp (a->idiag_src, b->idiag_src));
871 diff |= _DIFF(DST,
nl_addr_cmp (a->idiag_dst, b->idiag_dst));
872 diff |= _DIFF(IFINDEX, a->idiag_ifindex != b->idiag_ifindex);
873 diff |= _DIFF(EXPIRES, a->idiag_expires != b->idiag_expires);
874 diff |= _DIFF(RQUEUE, a->idiag_rqueue != b->idiag_rqueue);
875 diff |= _DIFF(WQUEUE, a->idiag_wqueue != b->idiag_wqueue);
876 diff |= _DIFF(UID, a->idiag_uid != b->idiag_uid);
877 diff |= _DIFF(INODE, a->idiag_inode != b->idiag_inode);
878 diff |= _DIFF(TOS, a->idiag_tos != b->idiag_tos);
879 diff |= _DIFF(TCLASS, a->idiag_tclass != b->idiag_tclass);
880 diff |= _DIFF(SHUTDOWN, a->idiag_shutdown != b->idiag_shutdown);
881 diff |= _DIFF(CONG, strcmp(a->idiag_cong, b->idiag_cong));
882 diff |= _DIFF(MEMINFO,
nl_object_diff((
struct nl_object *) a->idiag_meminfo, (
struct nl_object *) b->idiag_meminfo));
883 diff |= _DIFF(VEGASINFO,
nl_object_diff((
struct nl_object *) a->idiag_vegasinfo, (
struct nl_object *) b->idiag_vegasinfo));
884 diff |= _DIFF(TCPINFO, memcmp(&a->idiag_tcpinfo, &b->idiag_tcpinfo,
sizeof(a->idiag_tcpinfo)));
885 diff |= _DIFF(SKMEMINFO, memcmp(a->idiag_skmeminfo, b->idiag_skmeminfo,
sizeof(a->idiag_skmeminfo)));
890 static void idiagnl_keygen(
struct nl_object *obj, uint32_t *hashkey,
893 struct idiagnl_msg *msg = (
struct idiagnl_msg *)obj;
895 struct idiagnl_hash_key {
901 } __attribute__((packed)) key;
903 key_sz = sizeof(key);
904 key.family = msg->idiag_family;
907 key.sport = msg->idiag_sport;
908 key.dport = msg->idiag_dport;
910 if (msg->idiag_src) {
914 if (msg->idiag_dst) {
919 *hashkey = nl_hash(&key, key_sz, 0) % table_sz;
921 NL_DBG(5,
"idiagnl %p key (fam %d src_hash %d dst_hash %d sport %d dport %d) keysz %d, hash 0x%x\n",
922 msg, key.family, key.src_hash, key.dst_hash, key.sport, key.dport, key_sz, *hashkey);
928 struct nl_object_ops idiagnl_msg_obj_ops = {
929 .oo_name =
"idiag/idiag_msg",
930 .oo_size =
sizeof(
struct idiagnl_msg),
931 .oo_free_data = idiagnl_msg_free,
932 .oo_clone = idiagnl_msg_clone,
938 .oo_compare = idiagnl_compare,
939 .oo_keygen = idiagnl_keygen,
940 .oo_attrs2str = _idiagnl_attrs2str,
941 .oo_id_attrs = (IDIAGNL_ATTR_FAMILY |
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Dump object briefly on one line.
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Attribute validation policy.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
char * nl_msec2str(uint64_t msec, char *buf, size_t len)
Convert milliseconds to a character string.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
NUL terminated character string.
Dump all attributes but no statistics.
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.
char * nl_size2str(const size_t size, char *buf, const size_t len)
Convert a size toa character string.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
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_shutdown2str(uint8_t shutdown, char *buf, size_t len)
Convert shutdown state to string.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
char * idiagnl_tcpopts2str(uint8_t attrs, char *buf, size_t len)
Convert TCP option attributes to string.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
uint16_t minlen
Minimal length of payload required.
char * idiagnl_tcpstate2str(uint8_t state, char *buf, size_t len)
Convert inetdiag tcp states to strings.
int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
char * idiagnl_timer2str(int timer, char *buf, size_t len)
Convert inet diag timer types to strings.
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
struct nl_object * nl_object_clone(struct nl_object *obj)
Allocate a new object and copy all data from an existing object.
char * idiagnl_state2str(int state, char *buf, size_t len)
Convert inet diag socket states to strings.
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Dump all attributes including statistics.
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.
uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
Compute bitmask representing difference in attribute values.
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.