13 #include <netlink-private/netlink.h> 14 #include <netlink/hashtable.h> 15 #include <netlink/idiag/msg.h> 16 #include <netlink/idiag/meminfo.h> 17 #include <netlink/idiag/vegasinfo.h> 18 #include <linux/inet_diag.h> 22 #define IDIAGNL_ATTR_FAMILY (0x1 << 1) 23 #define IDIAGNL_ATTR_STATE (0x1 << 2) 24 #define IDIAGNL_ATTR_TIMER (0x1 << 3) 25 #define IDIAGNL_ATTR_RETRANS (0x1 << 4) 26 #define IDIAGNL_ATTR_SPORT (0x1 << 5) 27 #define IDIAGNL_ATTR_DPORT (0x1 << 6) 28 #define IDIAGNL_ATTR_SRC (0x1 << 7) 29 #define IDIAGNL_ATTR_DST (0x1 << 8) 30 #define IDIAGNL_ATTR_IFINDEX (0x1 << 9) 31 #define IDIAGNL_ATTR_EXPIRES (0x1 << 10) 32 #define IDIAGNL_ATTR_RQUEUE (0x1 << 11) 33 #define IDIAGNL_ATTR_WQUEUE (0x1 << 12) 34 #define IDIAGNL_ATTR_UID (0x1 << 13) 35 #define IDIAGNL_ATTR_INODE (0x1 << 14) 36 #define IDIAGNL_ATTR_TOS (0x1 << 15) 37 #define IDIAGNL_ATTR_TCLASS (0x1 << 16) 38 #define IDIAGNL_ATTR_SHUTDOWN (0x1 << 17) 39 #define IDIAGNL_ATTR_CONG (0x1 << 18) 40 #define IDIAGNL_ATTR_MEMINFO (0x1 << 19) 41 #define IDIAGNL_ATTR_VEGASINFO (0x1 << 20) 42 #define IDIAGNL_ATTR_TCPINFO (0x1 << 21) 43 #define IDIAGNL_ATTR_SKMEMINFO (0x1 << 22) 45 #define _INET_DIAG_ALL ((1<<(INET_DIAG_MAX+1))-1) 56 struct idiagnl_msg *idiagnl_msg_alloc(
void)
61 void idiagnl_msg_get(
struct idiagnl_msg *msg)
66 void idiagnl_msg_put(
struct idiagnl_msg *msg)
71 static struct nl_cache_ops idiagnl_msg_ops;
73 static int idiagnl_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
74 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
76 struct idiagnl_msg *msg = NULL;
79 if ((err = idiagnl_msg_parse(nlh, &msg)) < 0)
82 err = pp->pp_cb((
struct nl_object *) msg, pp);
88 static int idiagnl_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
90 int family = cache->c_iarg1;
91 int states = cache->c_iarg2;
106 static struct nl_cache_ops idiagnl_msg_ops = {
107 .co_name =
"idiag/idiag",
108 .co_hdrsize =
sizeof(
struct inet_diag_msg),
110 { TCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
111 { DCCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
112 END_OF_MSGTYPES_LIST,
114 .co_protocol = NETLINK_INET_DIAG,
115 .co_request_update = idiagnl_request_update,
116 .co_msg_parser = idiagnl_msg_parser,
117 .co_obj_ops = &idiagnl_msg_obj_ops,
120 static void __init idiagnl_init(
void)
125 static void __exit idiagnl_exit(
void)
147 struct nl_cache **result)
149 struct nl_cache *cache = NULL;
155 cache->c_iarg1 = family;
156 cache->c_iarg2 = states;
174 uint8_t idiagnl_msg_get_family(
const struct idiagnl_msg *msg)
176 return msg->idiag_family;
179 void idiagnl_msg_set_family(
struct idiagnl_msg *msg, uint8_t family)
181 msg->idiag_family = family;
182 msg->ce_mask |= IDIAGNL_ATTR_FAMILY;
185 uint8_t idiagnl_msg_get_state(
const struct idiagnl_msg *msg)
187 return msg->idiag_state;
190 void idiagnl_msg_set_state(
struct idiagnl_msg *msg, uint8_t state)
192 msg->idiag_state = state;
193 msg->ce_mask |= IDIAGNL_ATTR_STATE;
196 uint8_t idiagnl_msg_get_timer(
const struct idiagnl_msg *msg)
198 return msg->idiag_timer;
201 void idiagnl_msg_set_timer(
struct idiagnl_msg *msg, uint8_t timer)
203 msg->idiag_timer = timer;
204 msg->ce_mask |= IDIAGNL_ATTR_TIMER;
207 uint8_t idiagnl_msg_get_retrans(
const struct idiagnl_msg *msg)
209 return msg->idiag_retrans;
212 void idiagnl_msg_set_retrans(
struct idiagnl_msg *msg, uint8_t retrans)
214 msg->idiag_retrans = retrans;
215 msg->ce_mask |= IDIAGNL_ATTR_RETRANS;
218 uint16_t idiagnl_msg_get_sport(
struct idiagnl_msg *msg)
220 return msg->idiag_sport;
223 void idiagnl_msg_set_sport(
struct idiagnl_msg *msg, uint16_t port)
225 msg->idiag_sport = port;
226 msg->ce_mask |= IDIAGNL_ATTR_SPORT;
229 uint16_t idiagnl_msg_get_dport(
struct idiagnl_msg *msg)
231 return msg->idiag_dport;
234 void idiagnl_msg_set_dport(
struct idiagnl_msg *msg, uint16_t port)
236 msg->idiag_dport = port;
237 msg->ce_mask |= IDIAGNL_ATTR_DPORT;
240 struct nl_addr *idiagnl_msg_get_src(
const struct idiagnl_msg *msg)
242 return msg->idiag_src;
245 int idiagnl_msg_set_src(
struct idiagnl_msg *msg,
struct nl_addr *addr)
251 msg->idiag_src = addr;
252 msg->ce_mask |= IDIAGNL_ATTR_SRC;
257 struct nl_addr *idiagnl_msg_get_dst(
const struct idiagnl_msg *msg)
259 return msg->idiag_dst;
262 int idiagnl_msg_set_dst(
struct idiagnl_msg *msg,
struct nl_addr *addr)
268 msg->idiag_dst = addr;
269 msg->ce_mask |= IDIAGNL_ATTR_DST;
274 uint32_t idiagnl_msg_get_ifindex(
const struct idiagnl_msg *msg)
276 return msg->idiag_ifindex;
279 void idiagnl_msg_set_ifindex(
struct idiagnl_msg *msg, uint32_t ifindex)
281 msg->idiag_ifindex = ifindex;
282 msg->ce_mask |= IDIAGNL_ATTR_IFINDEX;
285 uint32_t idiagnl_msg_get_expires(
const struct idiagnl_msg *msg)
287 return msg->idiag_expires;
290 void idiagnl_msg_set_expires(
struct idiagnl_msg *msg, uint32_t expires)
292 msg->idiag_expires = expires;
293 msg->ce_mask |= IDIAGNL_ATTR_EXPIRES;
296 uint32_t idiagnl_msg_get_rqueue(
const struct idiagnl_msg *msg)
298 return msg->idiag_rqueue;
301 void idiagnl_msg_set_rqueue(
struct idiagnl_msg *msg, uint32_t rqueue)
303 msg->idiag_rqueue = rqueue;
304 msg->ce_mask |= IDIAGNL_ATTR_RQUEUE;
307 uint32_t idiagnl_msg_get_wqueue(
const struct idiagnl_msg *msg)
309 return msg->idiag_wqueue;
312 void idiagnl_msg_set_wqueue(
struct idiagnl_msg *msg, uint32_t wqueue)
314 msg->idiag_wqueue = wqueue;
315 msg->ce_mask |= IDIAGNL_ATTR_WQUEUE;
318 uint32_t idiagnl_msg_get_uid(
const struct idiagnl_msg *msg)
320 return msg->idiag_uid;
323 void idiagnl_msg_set_uid(
struct idiagnl_msg *msg, uint32_t uid)
325 msg->idiag_uid = uid;
326 msg->ce_mask |= IDIAGNL_ATTR_UID;
329 uint32_t idiagnl_msg_get_inode(
const struct idiagnl_msg *msg)
331 return msg->idiag_inode;
334 void idiagnl_msg_set_inode(
struct idiagnl_msg *msg, uint32_t inode)
336 msg->idiag_inode = inode;
337 msg->ce_mask |= IDIAGNL_ATTR_INODE;
340 uint8_t idiagnl_msg_get_tos(
const struct idiagnl_msg *msg)
342 return msg->idiag_tos;
345 void idiagnl_msg_set_tos(
struct idiagnl_msg *msg, uint8_t tos)
347 msg->idiag_tos = tos;
348 msg->ce_mask |= IDIAGNL_ATTR_TOS;
351 uint8_t idiagnl_msg_get_tclass(
const struct idiagnl_msg *msg)
353 return msg->idiag_tclass;
356 void idiagnl_msg_set_tclass(
struct idiagnl_msg *msg, uint8_t tclass)
358 msg->idiag_tclass = tclass;
359 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
362 uint8_t idiagnl_msg_get_shutdown(
const struct idiagnl_msg *msg)
364 return msg->idiag_shutdown;
367 void idiagnl_msg_set_shutdown(
struct idiagnl_msg *msg, uint8_t shutdown)
369 msg->idiag_shutdown = shutdown;
370 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
373 char *idiagnl_msg_get_cong(
const struct idiagnl_msg *msg)
375 return msg->idiag_cong;
378 void idiagnl_msg_set_cong(
struct idiagnl_msg *msg,
char *cong)
380 free (msg->idiag_cong);
381 msg->idiag_cong = strdup(cong);
382 msg->ce_mask |= IDIAGNL_ATTR_CONG;
385 struct idiagnl_meminfo *idiagnl_msg_get_meminfo(
const struct idiagnl_msg *msg)
387 return msg->idiag_meminfo;
390 void idiagnl_msg_set_meminfo(
struct idiagnl_msg *msg,
struct idiagnl_meminfo *minfo)
392 if (msg->idiag_meminfo)
393 idiagnl_meminfo_put(msg->idiag_meminfo);
395 idiagnl_meminfo_get(minfo);
396 msg->idiag_meminfo = minfo;
397 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
400 struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(
const struct idiagnl_msg *msg)
402 return msg->idiag_vegasinfo;
405 void idiagnl_msg_set_vegasinfo(
struct idiagnl_msg *msg,
struct idiagnl_vegasinfo *vinfo)
407 if (msg->idiag_vegasinfo)
408 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
410 idiagnl_vegasinfo_get(vinfo);
411 msg->idiag_vegasinfo = vinfo;
412 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
415 struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
417 return msg->idiag_tcpinfo;
420 void idiagnl_msg_set_tcpinfo(
struct idiagnl_msg *msg,
struct tcp_info *tinfo)
422 memcpy(&msg->idiag_tcpinfo, tinfo,
sizeof(
struct tcp_info));
423 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
428 static void idiag_msg_dump_line(
struct nl_object *a,
struct nl_dump_params *p)
430 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
431 char buf[64] = { 0 };
433 nl_dump_line(p,
"family: %s ", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
435 ntohs(msg->idiag_sport));
437 ntohs(msg->idiag_dport));
438 nl_dump(p,
"iif: %d ", msg->idiag_ifindex);
442 static void idiag_msg_dump_details(
struct nl_object *a,
struct nl_dump_params *p)
444 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
445 char buf[64], buf2[64];
447 nl_dump(p,
"\nfamily: %s\n", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
450 nl_dump(p,
"timer (%s, %s, retransmits: %d)\n",
452 nl_msec2str(msg->idiag_expires, buf2,
sizeof(buf2)),
456 ntohs(msg->idiag_sport));
458 ntohs(msg->idiag_dport));
460 nl_dump(p,
"ifindex: %d\n", msg->idiag_ifindex);
461 nl_dump(p,
"rqueue: %-6d wqueue: %-6d\n", msg->idiag_rqueue, msg->idiag_wqueue);
462 nl_dump(p,
"uid %d\n", msg->idiag_uid);
463 nl_dump(p,
"inode %d\n", msg->idiag_inode);
464 if (msg->idiag_shutdown) {
465 nl_dump(p,
"socket shutdown: %s\n",
470 nl_dump(p,
"tos: 0x%x\n", msg->idiag_tos);
471 nl_dump(p,
"traffic class: %d\n", msg->idiag_tclass);
472 nl_dump(p,
"congestion algorithm: %s\n", msg->idiag_cong ? msg->idiag_cong :
"");
475 static void idiag_msg_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
477 struct idiagnl_msg *msg = (
struct idiagnl_msg *) obj;
480 idiag_msg_dump_details(obj, p);
483 nl_dump(p,
"\tsocket state: %s\n",
486 nl_dump(p,
"\ttcp state: %s\n",
489 nl_dump(p,
"\tretransmits: %d\n",
490 msg->idiag_tcpinfo.tcpi_retransmits);
492 msg->idiag_tcpinfo.tcpi_probes);
494 msg->idiag_tcpinfo.tcpi_backoff);
498 nl_dump(p,
"\tsnd_wscale: %d\n", msg->idiag_tcpinfo.tcpi_snd_wscale);
499 nl_dump(p,
"\trcv_wscale: %d\n", msg->idiag_tcpinfo.tcpi_rcv_wscale);
500 nl_dump(p,
"\trto: %d\n", msg->idiag_tcpinfo.tcpi_rto);
501 nl_dump(p,
"\tato: %d\n", msg->idiag_tcpinfo.tcpi_ato);
506 nl_dump(p,
"\tunacked: %d\n", msg->idiag_tcpinfo.tcpi_unacked);
507 nl_dump(p,
"\tsacked: %d\n", msg->idiag_tcpinfo.tcpi_sacked);
509 nl_dump(p,
"\tlost: %d\n", msg->idiag_tcpinfo.tcpi_lost);
510 nl_dump(p,
"\tretransmit segments: %d\n",
511 msg->idiag_tcpinfo.tcpi_retrans);
513 msg->idiag_tcpinfo.tcpi_fackets);
514 nl_dump(p,
"\tlast data sent: %s\n",
515 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_sent, buf,
517 nl_dump(p,
"\tlast ack sent: %s\n",
518 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_sent, buf,
sizeof(buf)));
519 nl_dump(p,
"\tlast data recv: %s\n",
520 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_recv, buf,
522 nl_dump(p,
"\tlast ack recv: %s\n",
523 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_recv, buf,
528 nl_dump(p,
"\trcv ss threshold: %d\n",
529 msg->idiag_tcpinfo.tcpi_rcv_ssthresh);
530 nl_dump(p,
"\tsmoothed round trip time: %d\n",
531 msg->idiag_tcpinfo.tcpi_rtt);
532 nl_dump(p,
"\tround trip time variation: %d\n",
533 msg->idiag_tcpinfo.tcpi_rttvar);
534 nl_dump(p,
"\tsnd ss threshold: %s\n",
535 nl_size2str(msg->idiag_tcpinfo.tcpi_snd_ssthresh, buf,
537 nl_dump(p,
"\tsend congestion window: %d\n",
538 msg->idiag_tcpinfo.tcpi_snd_cwnd);
539 nl_dump(p,
"\tadvertised mss: %s\n",
542 nl_dump(p,
"\treordering: %d\n",
543 msg->idiag_tcpinfo.tcpi_reordering);
544 nl_dump(p,
"\trcv rround trip time: %d\n",
545 msg->idiag_tcpinfo.tcpi_rcv_rtt);
546 nl_dump(p,
"\treceive queue space: %s\n",
547 nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_space, buf,
549 nl_dump(p,
"\ttotal retransmits: %d\n",
550 msg->idiag_tcpinfo.tcpi_total_retrans);
553 if (msg->idiag_meminfo) {
574 if (msg->idiag_vegasinfo) {
576 nl_dump(p,
"\tvegas enabled: %d\n",
577 msg->idiag_vegasinfo->tcpv_enabled);
578 if (msg->idiag_vegasinfo->tcpv_enabled) {
580 msg->idiag_vegasinfo->tcpv_rttcnt);
581 nl_dump(p,
"\trtt (propagation delay): %d",
582 msg->idiag_vegasinfo->tcpv_rtt);
584 msg->idiag_vegasinfo->tcpv_minrtt);
589 if (msg->ce_mask & IDIAGNL_ATTR_MEMINFO) {
591 nl_dump(p,
"\trmem alloc: %d\n",
592 msg->idiag_skmeminfo[SK_MEMINFO_RMEM_ALLOC]);
594 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_RCVBUF],
596 nl_dump(p,
"\twmem alloc: %d\n",
597 msg->idiag_skmeminfo[SK_MEMINFO_WMEM_ALLOC]);
599 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_SNDBUF],
601 nl_dump(p,
"\tfwd alloc: %d\n",
602 msg->idiag_skmeminfo[SK_MEMINFO_FWD_ALLOC]);
603 nl_dump(p,
"\twmem queued: %s\n",
604 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_WMEM_QUEUED],
607 msg->idiag_skmeminfo[SK_MEMINFO_OPTMEM]);
609 msg->idiag_skmeminfo[SK_MEMINFO_BACKLOG]);
614 static void idiagnl_msg_free(
struct nl_object *a)
616 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
620 free(msg->idiag_cong);
623 idiagnl_meminfo_put(msg->idiag_meminfo);
624 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
627 static int idiagnl_msg_clone(
struct nl_object *_dst,
struct nl_object *_src)
629 struct idiagnl_msg *dst = (
struct idiagnl_msg *) _dst;
630 struct idiagnl_msg *src = (
struct idiagnl_msg *) _src;
632 dst->idiag_cong = NULL;
633 dst->idiag_src = NULL;
634 dst->idiag_dst = NULL;
635 dst->idiag_meminfo = NULL;
636 dst->idiag_vegasinfo = NULL;
637 dst->ce_mask &= ~(IDIAGNL_ATTR_CONG |
640 IDIAGNL_ATTR_MEMINFO |
641 IDIAGNL_ATTR_VEGASINFO);
643 if (src->idiag_cong) {
644 if (!(dst->idiag_cong = strdup(src->idiag_cong)))
646 dst->ce_mask |= IDIAGNL_ATTR_CONG;
649 if (src->idiag_src) {
652 dst->ce_mask |= IDIAGNL_ATTR_SRC;
655 if (src->idiag_dst) {
658 dst->ce_mask |= IDIAGNL_ATTR_DST;
661 if (src->idiag_meminfo) {
662 if (!(dst->idiag_meminfo = (
struct idiagnl_meminfo *)
nl_object_clone((
struct nl_object *) src->idiag_meminfo)))
664 dst->ce_mask |= IDIAGNL_ATTR_MEMINFO;
667 if (src->idiag_vegasinfo) {
668 if (!(dst->idiag_vegasinfo = (
struct idiagnl_vegasinfo *)
nl_object_clone((
struct nl_object *) src->idiag_vegasinfo)))
670 dst->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
676 static struct nla_policy ext_policy[INET_DIAG_MAX+1] = {
677 [INET_DIAG_MEMINFO] = { .
minlen =
sizeof(
struct inet_diag_meminfo) },
678 [INET_DIAG_INFO] = { .minlen =
sizeof(
struct tcp_info) },
679 [INET_DIAG_VEGASINFO] = { .minlen =
sizeof(
struct tcpvegas_info) },
681 [INET_DIAG_TOS] = { .type =
NLA_U8 },
682 [INET_DIAG_TCLASS] = { .type =
NLA_U8 },
684 [INET_DIAG_SKMEMINFO] = { .minlen = (
sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) },
685 [INET_DIAG_SHUTDOWN] = { .type =
NLA_U8 },
688 int idiagnl_msg_parse(
struct nlmsghdr *nlh,
struct idiagnl_msg **result)
690 struct idiagnl_msg *msg = NULL;
691 struct inet_diag_msg *raw_msg = NULL;
692 struct nl_addr *src = NULL, *dst = NULL;
693 struct nlattr *tb[INET_DIAG_MAX+1];
696 msg = idiagnl_msg_alloc();
700 err =
nlmsg_parse(nlh,
sizeof(
struct inet_diag_msg), tb, INET_DIAG_MAX,
706 msg->idiag_family = raw_msg->idiag_family;
707 msg->idiag_state = raw_msg->idiag_state;
708 msg->idiag_timer = raw_msg->idiag_timer;
709 msg->idiag_retrans = raw_msg->idiag_retrans;
710 msg->idiag_expires = raw_msg->idiag_expires;
711 msg->idiag_rqueue = raw_msg->idiag_rqueue;
712 msg->idiag_wqueue = raw_msg->idiag_wqueue;
713 msg->idiag_uid = raw_msg->idiag_uid;
714 msg->idiag_inode = raw_msg->idiag_inode;
715 msg->idiag_sport = raw_msg->id.idiag_sport;
716 msg->idiag_dport = raw_msg->id.idiag_dport;
717 msg->idiag_ifindex = raw_msg->id.idiag_if;
719 msg->ce_mask = (IDIAGNL_ATTR_FAMILY |
722 IDIAGNL_ATTR_RETRANS |
723 IDIAGNL_ATTR_EXPIRES |
724 IDIAGNL_ATTR_RQUEUE |
725 IDIAGNL_ATTR_WQUEUE |
730 IDIAGNL_ATTR_IFINDEX);
732 dst =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
733 sizeof(raw_msg->id.idiag_dst));
737 err = idiagnl_msg_set_dst(msg, dst);
743 src =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src,
744 sizeof(raw_msg->id.idiag_src));
748 err = idiagnl_msg_set_src(msg, src);
754 if (tb[INET_DIAG_TOS]) {
755 msg->idiag_tos =
nla_get_u8(tb[INET_DIAG_TOS]);
756 msg->ce_mask |= IDIAGNL_ATTR_TOS;
759 if (tb[INET_DIAG_TCLASS]) {
760 msg->idiag_tclass =
nla_get_u8(tb[INET_DIAG_TCLASS]);
761 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
764 if (tb[INET_DIAG_SHUTDOWN]) {
765 msg->idiag_shutdown =
nla_get_u8(tb[INET_DIAG_SHUTDOWN]);
766 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
769 if (tb[INET_DIAG_CONG]) {
770 msg->idiag_cong = nla_strdup(tb[INET_DIAG_CONG]);
771 msg->ce_mask |= IDIAGNL_ATTR_CONG;
774 if (tb[INET_DIAG_INFO]) {
775 nla_memcpy(&msg->idiag_tcpinfo, tb[INET_DIAG_INFO],
776 sizeof(msg->idiag_tcpinfo));
777 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
780 if (tb[INET_DIAG_MEMINFO]) {
781 struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc();
782 struct inet_diag_meminfo *raw_minfo = NULL;
787 raw_minfo = (
struct inet_diag_meminfo *)
790 idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem);
791 idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem);
792 idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem);
793 idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem);
795 msg->idiag_meminfo = minfo;
796 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
799 if (tb[INET_DIAG_VEGASINFO]) {
800 struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc();
801 struct tcpvegas_info *raw_vinfo = NULL;
806 raw_vinfo = (
struct tcpvegas_info *)
809 idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled);
810 idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt);
811 idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt);
812 idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt);
814 msg->idiag_vegasinfo = vinfo;
815 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
818 if (tb[INET_DIAG_SKMEMINFO]) {
819 nla_memcpy(&msg->idiag_skmeminfo, tb[INET_DIAG_SKMEMINFO],
820 sizeof(msg->idiag_skmeminfo));
821 msg->ce_mask |= IDIAGNL_ATTR_SKMEMINFO;
828 idiagnl_msg_put(msg);
836 static const struct trans_tbl idiagnl_attrs[] = {
837 __ADD(IDIAGNL_ATTR_FAMILY, family),
838 __ADD(IDIAGNL_ATTR_STATE, state),
839 __ADD(IDIAGNL_ATTR_TIMER, timer),
840 __ADD(IDIAGNL_ATTR_RETRANS, retrans),
841 __ADD(IDIAGNL_ATTR_SPORT, sport),
842 __ADD(IDIAGNL_ATTR_DPORT, dport),
843 __ADD(IDIAGNL_ATTR_SRC, src),
844 __ADD(IDIAGNL_ATTR_DST, dst),
845 __ADD(IDIAGNL_ATTR_IFINDEX, ifindex),
846 __ADD(IDIAGNL_ATTR_EXPIRES, expires),
847 __ADD(IDIAGNL_ATTR_RQUEUE, rqueue),
848 __ADD(IDIAGNL_ATTR_WQUEUE, wqueue),
849 __ADD(IDIAGNL_ATTR_UID, uid),
850 __ADD(IDIAGNL_ATTR_INODE, inode),
851 __ADD(IDIAGNL_ATTR_TOS, tos),
852 __ADD(IDIAGNL_ATTR_TCLASS, tclass),
853 __ADD(IDIAGNL_ATTR_SHUTDOWN, shutdown),
854 __ADD(IDIAGNL_ATTR_CONG, cong),
855 __ADD(IDIAGNL_ATTR_MEMINFO, meminfo),
856 __ADD(IDIAGNL_ATTR_VEGASINFO, vegasinfo),
857 __ADD(IDIAGNL_ATTR_TCPINFO, tcpinfo),
858 __ADD(IDIAGNL_ATTR_SKMEMINFO, skmeminfo),
861 static char *_idiagnl_attrs2str(
int attrs,
char *buf,
size_t len)
863 return __flags2str(attrs, buf, len, idiagnl_attrs,
864 ARRAY_SIZE(idiagnl_attrs));
867 static uint64_t idiagnl_compare(
struct nl_object *_a,
struct nl_object *_b,
868 uint64_t attrs,
int flags)
870 struct idiagnl_msg *a = (
struct idiagnl_msg *) _a;
871 struct idiagnl_msg *b = (
struct idiagnl_msg *) _b;
874 #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, IDIAGNL_ATTR_##ATTR, a, b, EXPR) 875 diff |= _DIFF(FAMILY, a->idiag_family != b->idiag_family);
876 diff |= _DIFF(STATE, a->idiag_state != b->idiag_state);
877 diff |= _DIFF(TIMER, a->idiag_timer != b->idiag_timer);
878 diff |= _DIFF(RETRANS, a->idiag_retrans != b->idiag_retrans);
879 diff |= _DIFF(SPORT, a->idiag_sport != b->idiag_sport);
880 diff |= _DIFF(DPORT, a->idiag_dport != b->idiag_dport);
881 diff |= _DIFF(SRC,
nl_addr_cmp (a->idiag_src, b->idiag_src));
882 diff |= _DIFF(DST,
nl_addr_cmp (a->idiag_dst, b->idiag_dst));
883 diff |= _DIFF(IFINDEX, a->idiag_ifindex != b->idiag_ifindex);
884 diff |= _DIFF(EXPIRES, a->idiag_expires != b->idiag_expires);
885 diff |= _DIFF(RQUEUE, a->idiag_rqueue != b->idiag_rqueue);
886 diff |= _DIFF(WQUEUE, a->idiag_wqueue != b->idiag_wqueue);
887 diff |= _DIFF(UID, a->idiag_uid != b->idiag_uid);
888 diff |= _DIFF(INODE, a->idiag_inode != b->idiag_inode);
889 diff |= _DIFF(TOS, a->idiag_tos != b->idiag_tos);
890 diff |= _DIFF(TCLASS, a->idiag_tclass != b->idiag_tclass);
891 diff |= _DIFF(SHUTDOWN, a->idiag_shutdown != b->idiag_shutdown);
892 diff |= _DIFF(CONG, strcmp(a->idiag_cong, b->idiag_cong));
893 diff |= _DIFF(MEMINFO,
nl_object_diff((
struct nl_object *) a->idiag_meminfo, (
struct nl_object *) b->idiag_meminfo));
894 diff |= _DIFF(VEGASINFO,
nl_object_diff((
struct nl_object *) a->idiag_vegasinfo, (
struct nl_object *) b->idiag_vegasinfo));
895 diff |= _DIFF(TCPINFO, memcmp(&a->idiag_tcpinfo, &b->idiag_tcpinfo,
sizeof(a->idiag_tcpinfo)));
896 diff |= _DIFF(SKMEMINFO, memcmp(a->idiag_skmeminfo, b->idiag_skmeminfo,
sizeof(a->idiag_skmeminfo)));
901 static void idiagnl_keygen(
struct nl_object *obj, uint32_t *hashkey,
904 struct idiagnl_msg *msg = (
struct idiagnl_msg *)obj;
906 struct idiagnl_hash_key {
912 } __attribute__((packed)) key;
914 key_sz =
sizeof(key);
915 key.family = msg->idiag_family;
918 key.sport = msg->idiag_sport;
919 key.dport = msg->idiag_dport;
921 if (msg->idiag_src) {
925 if (msg->idiag_dst) {
930 *hashkey = nl_hash(&key, key_sz, 0) % table_sz;
932 NL_DBG(5,
"idiagnl %p key (fam %d src_hash %d dst_hash %d sport %d dport %d) keysz %d, hash 0x%x\n",
933 msg, key.family, key.src_hash, key.dst_hash, key.sport, key.dport, key_sz, *hashkey);
939 struct nl_object_ops idiagnl_msg_obj_ops = {
940 .oo_name =
"idiag/idiag_msg",
941 .oo_size =
sizeof(
struct idiagnl_msg),
942 .oo_free_data = idiagnl_msg_free,
943 .oo_clone = idiagnl_msg_clone,
949 .oo_compare = idiagnl_compare,
950 .oo_keygen = idiagnl_keygen,
951 .oo_attrs2str = _idiagnl_attrs2str,
952 .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 nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
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.
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 32-bit 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.