12 #include <netlink-private/netlink.h>
13 #include <netlink/idiag/msg.h>
14 #include <netlink/idiag/meminfo.h>
15 #include <netlink/idiag/vegasinfo.h>
16 #include <linux/inet_diag.h>
26 struct idiagnl_msg *idiagnl_msg_alloc(
void)
31 void idiagnl_msg_get(
struct idiagnl_msg *msg)
36 void idiagnl_msg_put(
struct idiagnl_msg *msg)
41 static struct nl_cache_ops idiagnl_msg_ops;
43 static int idiagnl_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
44 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
46 struct idiagnl_msg *msg = NULL;
49 if ((err = idiagnl_msg_parse(nlh, &msg)) < 0)
52 err = pp->pp_cb((
struct nl_object *) msg, pp);
58 static int idiagnl_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
60 int family = cache->c_iarg1;
61 int states = cache->c_iarg2;
66 static struct nl_cache_ops idiagnl_msg_ops = {
67 .co_name =
"idiag/idiag",
68 .co_hdrsize =
sizeof(
struct inet_diag_msg),
70 { IDIAG_TCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
71 { IDIAG_DCCPDIAG_GETSOCK, NL_ACT_NEW,
"new" },
74 .co_protocol = NETLINK_INET_DIAG,
75 .co_request_update = idiagnl_request_update,
76 .co_msg_parser = idiagnl_msg_parser,
77 .co_obj_ops = &idiagnl_msg_obj_ops,
80 static void __init idiagnl_init(
void)
85 static void __exit idiagnl_exit(
void)
107 struct nl_cache **result)
109 struct nl_cache *cache = NULL;
115 cache->c_iarg1 = family;
116 cache->c_iarg2 = states;
134 uint8_t idiagnl_msg_get_family(
const struct idiagnl_msg *msg)
136 return msg->idiag_family;
139 void idiagnl_msg_set_family(
struct idiagnl_msg *msg, uint8_t family)
141 msg->idiag_family = family;
144 uint8_t idiagnl_msg_get_state(
const struct idiagnl_msg *msg)
146 return msg->idiag_state;
149 void idiagnl_msg_set_state(
struct idiagnl_msg *msg, uint8_t state)
151 msg->idiag_state = state;
154 uint8_t idiagnl_msg_get_timer(
const struct idiagnl_msg *msg)
156 return msg->idiag_timer;
159 void idiagnl_msg_set_timer(
struct idiagnl_msg *msg, uint8_t timer)
161 msg->idiag_timer = timer;
164 uint8_t idiagnl_msg_get_retrans(
const struct idiagnl_msg *msg)
166 return msg->idiag_retrans;
169 void idiagnl_msg_set_retrans(
struct idiagnl_msg *msg, uint8_t retrans)
171 msg->idiag_retrans = retrans;
174 uint16_t idiagnl_msg_get_sport(
struct idiagnl_msg *msg)
176 return msg->idiag_sport;
179 void idiagnl_msg_set_sport(
struct idiagnl_msg *msg, uint16_t port)
181 msg->idiag_sport = port;
184 uint16_t idiagnl_msg_get_dport(
struct idiagnl_msg *msg)
186 return msg->idiag_dport;
189 void idiagnl_msg_set_dport(
struct idiagnl_msg *msg, uint16_t port)
191 msg->idiag_dport = port;
194 struct nl_addr *idiagnl_msg_get_src(
const struct idiagnl_msg *msg)
196 return msg->idiag_src;
199 int idiagnl_msg_set_src(
struct idiagnl_msg *msg,
struct nl_addr *addr)
205 msg->idiag_src = addr;
210 struct nl_addr *idiagnl_msg_get_dst(
const struct idiagnl_msg *msg)
212 return msg->idiag_dst;
215 int idiagnl_msg_set_dst(
struct idiagnl_msg *msg,
struct nl_addr *addr)
221 msg->idiag_dst = addr;
226 uint32_t idiagnl_msg_get_ifindex(
const struct idiagnl_msg *msg)
228 return msg->idiag_ifindex;
231 void idiagnl_msg_set_ifindex(
struct idiagnl_msg *msg, uint32_t ifindex)
233 msg->idiag_ifindex = ifindex;
236 uint32_t idiagnl_msg_get_expires(
const struct idiagnl_msg *msg)
238 return msg->idiag_expires;
241 void idiagnl_msg_set_expires(
struct idiagnl_msg *msg, uint32_t expires)
243 msg->idiag_expires = expires;
246 uint32_t idiagnl_msg_get_rqueue(
const struct idiagnl_msg *msg)
248 return msg->idiag_rqueue;
251 void idiagnl_msg_set_rqueue(
struct idiagnl_msg *msg, uint32_t rqueue)
253 msg->idiag_rqueue = rqueue;
256 uint32_t idiagnl_msg_get_wqueue(
const struct idiagnl_msg *msg)
258 return msg->idiag_wqueue;
261 void idiagnl_msg_set_wqueue(
struct idiagnl_msg *msg, uint32_t wqueue)
263 msg->idiag_wqueue = wqueue;
266 uint32_t idiagnl_msg_get_uid(
const struct idiagnl_msg *msg)
268 return msg->idiag_uid;
271 void idiagnl_msg_set_uid(
struct idiagnl_msg *msg, uint32_t uid)
273 msg->idiag_uid = uid;
276 uint32_t idiagnl_msg_get_inode(
const struct idiagnl_msg *msg)
278 return msg->idiag_inode;
281 void idiagnl_msg_set_inode(
struct idiagnl_msg *msg, uint32_t inode)
283 msg->idiag_inode = inode;
286 uint8_t idiagnl_msg_get_tos(
const struct idiagnl_msg *msg)
288 return msg->idiag_tos;
291 void idiagnl_msg_set_tos(
struct idiagnl_msg *msg, uint8_t tos)
293 msg->idiag_tos = tos;
296 uint8_t idiagnl_msg_get_tclass(
const struct idiagnl_msg *msg)
298 return msg->idiag_tclass;
301 void idiagnl_msg_set_tclass(
struct idiagnl_msg *msg, uint8_t tclass)
303 msg->idiag_tclass = tclass;
306 uint8_t idiagnl_msg_get_shutdown(
const struct idiagnl_msg *msg)
308 return msg->idiag_shutdown;
311 void idiagnl_msg_set_shutdown(
struct idiagnl_msg *msg, uint8_t shutdown)
313 msg->idiag_shutdown = shutdown;
316 char *idiagnl_msg_get_cong(
const struct idiagnl_msg *msg)
318 return msg->idiag_cong;
321 void idiagnl_msg_set_cong(
struct idiagnl_msg *msg,
char *cong)
323 msg->idiag_cong = strdup(cong);
326 struct idiagnl_meminfo *idiagnl_msg_get_meminfo(
const struct idiagnl_msg *msg)
328 return msg->idiag_meminfo;
331 void idiagnl_msg_set_meminfo(
struct idiagnl_msg *msg,
struct idiagnl_meminfo
334 if (msg->idiag_meminfo)
335 idiagnl_meminfo_put(msg->idiag_meminfo);
337 idiagnl_meminfo_get(minfo);
338 msg->idiag_meminfo = minfo;
341 struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(
const struct idiagnl_msg *msg)
343 return msg->idiag_vegasinfo;
346 void idiagnl_msg_set_vegasinfo(
struct idiagnl_msg *msg,
struct idiagnl_vegasinfo
349 if (msg->idiag_vegasinfo)
350 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
352 idiagnl_vegasinfo_get(vinfo);
353 msg->idiag_vegasinfo = vinfo;
356 struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
358 return msg->idiag_tcpinfo;
361 void idiagnl_msg_set_tcpinfo(
struct idiagnl_msg *msg,
struct tcp_info *tinfo)
363 memcpy(&msg->idiag_tcpinfo, tinfo,
sizeof(
struct tcp_info));
368 static void idiag_msg_dump_line(
struct nl_object *a,
struct nl_dump_params *p)
370 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
371 char buf[64] = { 0 };
373 nl_dump_line(p,
"family: %s ", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
375 ntohs(msg->idiag_sport));
377 ntohs(msg->idiag_dport));
378 nl_dump(p,
"iif: %d ", msg->idiag_ifindex);
382 static void idiag_msg_dump_details(
struct nl_object *a,
struct nl_dump_params *p)
384 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
385 char buf[64], buf2[64];
387 nl_dump(p,
"\nfamily: %s\n", nl_af2str(msg->idiag_family, buf,
sizeof(buf)));
390 nl_dump(p,
"timer (%s, %s, retransmits: %d)\n",
392 nl_msec2str(msg->idiag_expires, buf2,
sizeof(buf2)),
396 ntohs(msg->idiag_sport));
398 ntohs(msg->idiag_dport));
400 nl_dump(p,
"ifindex: %d\n", msg->idiag_ifindex);
401 nl_dump(p,
"rqueue: %-6d wqueue: %-6d\n", msg->idiag_rqueue, msg->idiag_wqueue);
402 nl_dump(p,
"uid %d\n", msg->idiag_uid);
403 nl_dump(p,
"inode %d\n", msg->idiag_inode);
404 if (msg->idiag_shutdown) {
405 nl_dump(p,
"socket shutdown: %s\n",
410 nl_dump(p,
"tos: 0x%x\n", msg->idiag_tos);
411 nl_dump(p,
"traffic class: %d\n", msg->idiag_tclass);
412 nl_dump(p,
"congestion algorithm: %s\n", msg->idiag_cong);
415 static void idiag_msg_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
417 struct idiagnl_msg *msg = (
struct idiagnl_msg *) obj;
420 idiag_msg_dump_details(obj, p);
423 nl_dump(p,
"\tsocket state: %s\n",
426 nl_dump(p,
"\ttcp state: %s\n",
429 nl_dump(p,
"\tretransmits: %d\n",
430 msg->idiag_tcpinfo.tcpi_retransmits);
432 msg->idiag_tcpinfo.tcpi_probes);
434 msg->idiag_tcpinfo.tcpi_backoff);
438 nl_dump(p,
"\tsnd_wscale: %d\n", msg->idiag_tcpinfo.tcpi_snd_wscale);
439 nl_dump(p,
"\trcv_wscale: %d\n", msg->idiag_tcpinfo.tcpi_rcv_wscale);
440 nl_dump(p,
"\trto: %d\n", msg->idiag_tcpinfo.tcpi_rto);
441 nl_dump(p,
"\tato: %d\n", msg->idiag_tcpinfo.tcpi_ato);
446 nl_dump(p,
"\tunacked: %d\n", msg->idiag_tcpinfo.tcpi_unacked);
447 nl_dump(p,
"\tsacked: %d\n", msg->idiag_tcpinfo.tcpi_sacked);
449 nl_dump(p,
"\tlost: %d\n", msg->idiag_tcpinfo.tcpi_lost);
450 nl_dump(p,
"\tretransmit segments: %d\n",
451 msg->idiag_tcpinfo.tcpi_retrans);
453 msg->idiag_tcpinfo.tcpi_fackets);
454 nl_dump(p,
"\tlast data sent: %s\n",
455 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_sent, buf,
457 nl_dump(p,
"\tlast ack sent: %s\n",
458 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_sent, buf,
sizeof(buf)));
459 nl_dump(p,
"\tlast data recv: %s\n",
460 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_data_recv, buf,
462 nl_dump(p,
"\tlast ack recv: %s\n",
463 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_recv, buf,
468 nl_dump(p,
"\trcv ss threshold: %d\n",
469 msg->idiag_tcpinfo.tcpi_rcv_ssthresh);
470 nl_dump(p,
"\tsmoothed round trip time: %d\n",
471 msg->idiag_tcpinfo.tcpi_rtt);
472 nl_dump(p,
"\tround trip time variation: %d\n",
473 msg->idiag_tcpinfo.tcpi_rttvar);
474 nl_dump(p,
"\tsnd ss threshold: %s\n",
475 nl_size2str(msg->idiag_tcpinfo.tcpi_snd_ssthresh, buf,
477 nl_dump(p,
"\tsend congestion window: %d\n",
478 msg->idiag_tcpinfo.tcpi_snd_cwnd);
479 nl_dump(p,
"\tadvertised mss: %s\n",
482 nl_dump(p,
"\treordering: %d\n",
483 msg->idiag_tcpinfo.tcpi_reordering);
484 nl_dump(p,
"\trcv rround trip time: %d\n",
485 msg->idiag_tcpinfo.tcpi_rcv_rtt);
486 nl_dump(p,
"\treceive queue space: %s\n",
487 nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_space, buf,
489 nl_dump(p,
"\ttotal retransmits: %d\n",
490 msg->idiag_tcpinfo.tcpi_total_retrans);
493 if (msg->idiag_meminfo) {
514 if (msg->idiag_vegasinfo) {
516 nl_dump(p,
"\tvegas enabled: %d\n",
517 msg->idiag_vegasinfo->tcpv_enabled);
518 if (msg->idiag_vegasinfo->tcpv_enabled) {
520 msg->idiag_vegasinfo->tcpv_rttcnt);
521 nl_dump(p,
"\trtt (propagation delay): %d",
522 msg->idiag_vegasinfo->tcpv_rtt);
524 msg->idiag_vegasinfo->tcpv_minrtt);
530 nl_dump(p,
"\trmem alloc: %d\n",
531 msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_RMEM_ALLOC]);
533 nl_size2str(msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_RCVBUF],
535 nl_dump(p,
"\twmem alloc: %d\n",
536 msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_WMEM_ALLOC]);
538 nl_size2str(msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_SNDBUF],
540 nl_dump(p,
"\tfwd alloc: %d\n",
541 msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_FWD_ALLOC]);
542 nl_dump(p,
"\twmem queued: %s\n",
543 nl_size2str(msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_WMEM_QUEUED],
546 msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_OPTMEM]);
548 msg->idiag_skmeminfo[IDIAG_SK_MEMINFO_BACKLOG]);
552 static void idiagnl_msg_free(
struct nl_object *a)
554 struct idiagnl_msg *msg = (
struct idiagnl_msg *) a;
558 free(msg->idiag_cong);
561 idiagnl_meminfo_put(msg->idiag_meminfo);
562 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
565 static int idiagnl_msg_clone(
struct nl_object *_dst,
struct nl_object *_src)
567 struct idiagnl_msg *dst = (
struct idiagnl_msg *) _dst;
568 struct idiagnl_msg *src = (
struct idiagnl_msg *) _src;
581 static struct nla_policy ext_policy[IDIAG_ATTR_MAX] = {
582 [IDIAG_ATTR_MEMINFO] = { .
minlen =
sizeof(
struct inet_diag_meminfo) },
583 [IDIAG_ATTR_INFO] = { .minlen =
sizeof(
struct tcp_info) },
584 [IDIAG_ATTR_VEGASINFO] = { .minlen =
sizeof(
struct tcpvegas_info) },
586 [IDIAG_ATTR_TOS] = { .type =
NLA_U8 },
587 [IDIAG_ATTR_TCLASS] = { .type =
NLA_U8 },
588 [IDIAG_ATTR_SKMEMINFO] = { .minlen = (
sizeof(uint32_t) * IDIAG_SK_MEMINFO_VARS) },
589 [IDIAG_ATTR_SHUTDOWN] = { .type =
NLA_U8 },
592 int idiagnl_msg_parse(
struct nlmsghdr *nlh,
struct idiagnl_msg **result)
594 struct idiagnl_msg *msg = NULL;
595 struct inet_diag_msg *raw_msg = NULL;
596 struct nl_addr *src = NULL, *dst = NULL;
597 struct nlattr *tb[IDIAG_ATTR_MAX];
600 msg = idiagnl_msg_alloc();
604 err =
nlmsg_parse(nlh,
sizeof(
struct inet_diag_msg), tb, IDIAG_ATTR_MAX,
610 msg->idiag_family = raw_msg->idiag_family;
611 msg->idiag_state = raw_msg->idiag_state;
612 msg->idiag_timer = raw_msg->idiag_timer;
613 msg->idiag_retrans = raw_msg->idiag_retrans;
614 msg->idiag_expires = raw_msg->idiag_expires;
615 msg->idiag_rqueue = raw_msg->idiag_rqueue;
616 msg->idiag_wqueue = raw_msg->idiag_wqueue;
617 msg->idiag_uid = raw_msg->idiag_uid;
618 msg->idiag_inode = raw_msg->idiag_inode;
619 msg->idiag_sport = raw_msg->id.idiag_sport;
620 msg->idiag_dport = raw_msg->id.idiag_dport;
621 msg->idiag_ifindex = raw_msg->id.idiag_if;
623 dst =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
624 sizeof(raw_msg->id.idiag_dst));
628 err = idiagnl_msg_set_dst(msg, dst);
634 src =
nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src,
635 sizeof(raw_msg->id.idiag_src));
639 err = idiagnl_msg_set_src(msg, src);
645 if (tb[IDIAG_ATTR_TOS])
646 msg->idiag_tos =
nla_get_u8(tb[IDIAG_ATTR_TOS]);
648 if (tb[IDIAG_ATTR_TCLASS])
649 msg->idiag_tclass =
nla_get_u8(tb[IDIAG_ATTR_TCLASS]);
651 if (tb[IDIAG_ATTR_SHUTDOWN])
652 msg->idiag_shutdown =
nla_get_u8(tb[IDIAG_ATTR_SHUTDOWN]);
654 if (tb[IDIAG_ATTR_CONG])
655 msg->idiag_cong = nla_strdup(tb[IDIAG_ATTR_CONG]);
657 if (tb[IDIAG_ATTR_INFO])
658 nla_memcpy(&msg->idiag_tcpinfo, tb[IDIAG_ATTR_INFO],
659 sizeof(msg->idiag_tcpinfo));
661 if (tb[IDIAG_ATTR_MEMINFO]) {
662 struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc();
663 struct inet_diag_meminfo *raw_minfo = NULL;
668 raw_minfo = (
struct inet_diag_meminfo *)
671 idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem);
672 idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem);
673 idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem);
674 idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem);
676 msg->idiag_meminfo = minfo;
679 if (tb[IDIAG_ATTR_VEGASINFO]) {
680 struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc();
681 struct tcpvegas_info *raw_vinfo = NULL;
686 raw_vinfo = (
struct tcpvegas_info *)
689 idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled);
690 idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt);
691 idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt);
692 idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt);
694 msg->idiag_vegasinfo = vinfo;
697 if (tb[IDIAG_ATTR_SKMEMINFO])
698 nla_memcpy(&msg->idiag_skmeminfo, tb[IDIAG_ATTR_SKMEMINFO],
699 sizeof(msg->idiag_skmeminfo));
705 idiagnl_msg_put(msg);
714 struct nl_object_ops idiagnl_msg_obj_ops = {
715 .oo_name =
"idiag/idiag_msg",
716 .oo_size =
sizeof(
struct idiagnl_msg),
717 .oo_free_data = idiagnl_msg_free,
718 .oo_clone = idiagnl_msg_clone,
725 .oo_id_attrs = (IDIAG_ATTR_INFO)