libnl: /data/src/libnl/lib/idiag/idiag_msg_obj.c Source File

libnl 3.12.0

idiag_msg_obj.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
4 */
5
6#include "nl-default.h"
7
8#include <linux/inet_diag.h>
9
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>
15
16#include "nl-idiag.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"
20
21/** @cond SKIP */
22struct idiagnl_msg {
23 NLHDR_COMMON
24
25 uint8_t idiag_family;
26 uint8_t idiag_state;
27 uint8_t idiag_timer;
28 uint8_t idiag_retrans;
29 uint16_t idiag_sport;
30 uint16_t idiag_dport;
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;
37 uint32_t idiag_uid;
38 uint32_t idiag_inode;
39
40 uint8_t idiag_tos;
41 uint8_t idiag_tclass;
42 uint8_t idiag_shutdown;
43 char * idiag_cong;
44 struct idiagnl_meminfo * idiag_meminfo;
45 struct idiagnl_vegasinfo * idiag_vegasinfo;
46 struct tcp_info idiag_tcpinfo;
47 uint32_t idiag_skmeminfo[SK_MEMINFO_VARS];
48};
49
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)
72
73#define _INET_DIAG_ALL ((1<<(INET_DIAG_MAX+1))-1)
74/** @endcond */
75
76/**
77 * @ingroup idiag
78 * @defgroup idiagnl_msg Inet Diag Messages
79 *
80 * @details
81 * @idiagnl_doc{idiagnl_msg, Inet Diag Message Documentation}
82 * @{
83 */
84struct idiagnl_msg *idiagnl_msg_alloc(void)
85{
86 return (struct idiagnl_msg *) nl_object_alloc(&idiagnl_msg_obj_ops);
87}
88
89void idiagnl_msg_get(struct idiagnl_msg *msg)
90{
91 nl_object_get((struct nl_object *) msg);
92}
93
94void idiagnl_msg_put(struct idiagnl_msg *msg)
95{
96 nl_object_put((struct nl_object *) msg);
97}
98
99static struct nl_cache_ops idiagnl_msg_ops;
100
101static int idiagnl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
102 struct nlmsghdr *nlh, struct nl_parser_param *pp)
103{
104 struct idiagnl_msg *msg = NULL;
105 int err = 0;
106
107 if ((err = idiagnl_msg_parse(nlh, &msg)) < 0)
108 return err;
109
110 err = pp->pp_cb((struct nl_object *) msg, pp);
111 idiagnl_msg_put(msg);
112
113 return err;
114}
115
116static int idiagnl_request_update(struct nl_cache *cache, struct nl_sock *sk)
117{
118 int family = cache->c_iarg1;
119 int states = cache->c_iarg2;
120
121 /* idiagnl_send_simple()'s "ext" argument is u16, which is too small for _INET_DIAG_ALL,
122 * which is more than 16 bits on recent kernels.
123 *
124 * Actually, internally idiagnl_send_simple() sets "struct inet_diag_req"'s "idiag_ext"
125 * field, which is only 8 bits. So, it's even worse.
126 *
127 * FIXME: this probably should be fixed (by adding idiagnl_send_simple2() function), but for
128 * the moment it means we cannot request more than 0xFF.
129 */
130
131 return idiagnl_send_simple(sk, 0, family, states, (uint16_t) _INET_DIAG_ALL);
132}
133
134static struct nl_cache_ops idiagnl_msg_ops = {
135 .co_name = "idiag/idiag",
136 .co_hdrsize = sizeof(struct inet_diag_msg),
137 .co_msgtypes = {
138 { TCPDIAG_GETSOCK, NL_ACT_NEW, "new" },
139 { DCCPDIAG_GETSOCK, NL_ACT_NEW, "new" },
140 END_OF_MSGTYPES_LIST,
141 },
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,
146};
147
148static void _nl_init idiagnl_init(void)
149{
150 nl_cache_mngt_register(&idiagnl_msg_ops);
151}
152
153static void _nl_exit idiagnl_exit(void)
154{
155 nl_cache_mngt_unregister(&idiagnl_msg_ops);
156}
157
158/**
159 * @name Cache Management
160 * @{
161 */
162
163/**
164 * Build an inetdiag cache to hold socket state information.
165 * @arg sk Netlink socket
166 * @arg family The address family to query
167 * @arg states Socket states to query
168 * @arg result Result pointer
169 *
170 * @note The caller is responsible for destroying and free the cache after using
171 * it.
172 * @return 0 on success of a negative error code.
173 */
174 int idiagnl_msg_alloc_cache(struct nl_sock *sk, int family, int states,
175 struct nl_cache **result)
176{
177 struct nl_cache *cache = NULL;
178 int err;
179
180 if (!(cache = nl_cache_alloc(&idiagnl_msg_ops)))
181 return -NLE_NOMEM;
182
183 cache->c_iarg1 = family;
184 cache->c_iarg2 = states;
185
186 if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
187 free(cache);
188 return err;
189 }
190
191 *result = cache;
192 return 0;
193}
194
195/** @} */
196
197/**
198 * @name Attributes
199 * @{
200 */
201
202uint8_t idiagnl_msg_get_family(const struct idiagnl_msg *msg)
203{
204 return msg->idiag_family;
205}
206
207void idiagnl_msg_set_family(struct idiagnl_msg *msg, uint8_t family)
208{
209 msg->idiag_family = family;
210 msg->ce_mask |= IDIAGNL_ATTR_FAMILY;
211}
212
213uint8_t idiagnl_msg_get_state(const struct idiagnl_msg *msg)
214{
215 return msg->idiag_state;
216}
217
218void idiagnl_msg_set_state(struct idiagnl_msg *msg, uint8_t state)
219{
220 msg->idiag_state = state;
221 msg->ce_mask |= IDIAGNL_ATTR_STATE;
222}
223
224uint8_t idiagnl_msg_get_timer(const struct idiagnl_msg *msg)
225{
226 return msg->idiag_timer;
227}
228
229void idiagnl_msg_set_timer(struct idiagnl_msg *msg, uint8_t timer)
230{
231 msg->idiag_timer = timer;
232 msg->ce_mask |= IDIAGNL_ATTR_TIMER;
233}
234
235uint8_t idiagnl_msg_get_retrans(const struct idiagnl_msg *msg)
236{
237 return msg->idiag_retrans;
238}
239
240void idiagnl_msg_set_retrans(struct idiagnl_msg *msg, uint8_t retrans)
241{
242 msg->idiag_retrans = retrans;
243 msg->ce_mask |= IDIAGNL_ATTR_RETRANS;
244}
245
246uint16_t idiagnl_msg_get_sport(struct idiagnl_msg *msg)
247{
248 return msg->idiag_sport;
249}
250
251void idiagnl_msg_set_sport(struct idiagnl_msg *msg, uint16_t port)
252{
253 msg->idiag_sport = port;
254 msg->ce_mask |= IDIAGNL_ATTR_SPORT;
255}
256
257uint16_t idiagnl_msg_get_dport(struct idiagnl_msg *msg)
258{
259 return msg->idiag_dport;
260}
261
262void idiagnl_msg_set_dport(struct idiagnl_msg *msg, uint16_t port)
263{
264 msg->idiag_dport = port;
265 msg->ce_mask |= IDIAGNL_ATTR_DPORT;
266}
267
268struct nl_addr *idiagnl_msg_get_src(const struct idiagnl_msg *msg)
269{
270 return msg->idiag_src;
271}
272
273int idiagnl_msg_set_src(struct idiagnl_msg *msg, struct nl_addr *addr)
274{
275 if (msg->idiag_src)
276 nl_addr_put(msg->idiag_src);
277
278 nl_addr_get(addr);
279 msg->idiag_src = addr;
280 msg->ce_mask |= IDIAGNL_ATTR_SRC;
281
282 return 0;
283}
284
285struct nl_addr *idiagnl_msg_get_dst(const struct idiagnl_msg *msg)
286{
287 return msg->idiag_dst;
288}
289
290int idiagnl_msg_set_dst(struct idiagnl_msg *msg, struct nl_addr *addr)
291{
292 if (msg->idiag_dst)
293 nl_addr_put(msg->idiag_dst);
294
295 nl_addr_get(addr);
296 msg->idiag_dst = addr;
297 msg->ce_mask |= IDIAGNL_ATTR_DST;
298
299 return 0;
300}
301
302uint32_t idiagnl_msg_get_ifindex(const struct idiagnl_msg *msg)
303{
304 return msg->idiag_ifindex;
305}
306
307void idiagnl_msg_set_ifindex(struct idiagnl_msg *msg, uint32_t ifindex)
308{
309 msg->idiag_ifindex = ifindex;
310 msg->ce_mask |= IDIAGNL_ATTR_IFINDEX;
311}
312
313uint32_t idiagnl_msg_get_expires(const struct idiagnl_msg *msg)
314{
315 return msg->idiag_expires;
316}
317
318void idiagnl_msg_set_expires(struct idiagnl_msg *msg, uint32_t expires)
319{
320 msg->idiag_expires = expires;
321 msg->ce_mask |= IDIAGNL_ATTR_EXPIRES;
322}
323
324uint32_t idiagnl_msg_get_rqueue(const struct idiagnl_msg *msg)
325{
326 return msg->idiag_rqueue;
327}
328
329void idiagnl_msg_set_rqueue(struct idiagnl_msg *msg, uint32_t rqueue)
330{
331 msg->idiag_rqueue = rqueue;
332 msg->ce_mask |= IDIAGNL_ATTR_RQUEUE;
333}
334
335uint32_t idiagnl_msg_get_wqueue(const struct idiagnl_msg *msg)
336{
337 return msg->idiag_wqueue;
338}
339
340void idiagnl_msg_set_wqueue(struct idiagnl_msg *msg, uint32_t wqueue)
341{
342 msg->idiag_wqueue = wqueue;
343 msg->ce_mask |= IDIAGNL_ATTR_WQUEUE;
344}
345
346uint32_t idiagnl_msg_get_uid(const struct idiagnl_msg *msg)
347{
348 return msg->idiag_uid;
349}
350
351void idiagnl_msg_set_uid(struct idiagnl_msg *msg, uint32_t uid)
352{
353 msg->idiag_uid = uid;
354 msg->ce_mask |= IDIAGNL_ATTR_UID;
355}
356
357uint32_t idiagnl_msg_get_inode(const struct idiagnl_msg *msg)
358{
359 return msg->idiag_inode;
360}
361
362void idiagnl_msg_set_inode(struct idiagnl_msg *msg, uint32_t inode)
363{
364 msg->idiag_inode = inode;
365 msg->ce_mask |= IDIAGNL_ATTR_INODE;
366}
367
368uint8_t idiagnl_msg_get_tos(const struct idiagnl_msg *msg)
369{
370 return msg->idiag_tos;
371}
372
373void idiagnl_msg_set_tos(struct idiagnl_msg *msg, uint8_t tos)
374{
375 msg->idiag_tos = tos;
376 msg->ce_mask |= IDIAGNL_ATTR_TOS;
377}
378
379uint8_t idiagnl_msg_get_tclass(const struct idiagnl_msg *msg)
380{
381 return msg->idiag_tclass;
382}
383
384void idiagnl_msg_set_tclass(struct idiagnl_msg *msg, uint8_t tclass)
385{
386 msg->idiag_tclass = tclass;
387 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
388}
389
390uint8_t idiagnl_msg_get_shutdown(const struct idiagnl_msg *msg)
391{
392 return msg->idiag_shutdown;
393}
394
395void idiagnl_msg_set_shutdown(struct idiagnl_msg *msg, uint8_t shutdown)
396{
397 msg->idiag_shutdown = shutdown;
398 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
399}
400
401char *idiagnl_msg_get_cong(const struct idiagnl_msg *msg)
402{
403 return msg->idiag_cong;
404}
405
406void idiagnl_msg_set_cong(struct idiagnl_msg *msg, char *cong)
407{
408 free (msg->idiag_cong);
409 msg->idiag_cong = strdup(cong);
410 msg->ce_mask |= IDIAGNL_ATTR_CONG;
411}
412
413struct idiagnl_meminfo *idiagnl_msg_get_meminfo(const struct idiagnl_msg *msg)
414{
415 return msg->idiag_meminfo;
416}
417
418void idiagnl_msg_set_meminfo(struct idiagnl_msg *msg, struct idiagnl_meminfo *minfo)
419{
420 if (msg->idiag_meminfo)
421 idiagnl_meminfo_put(msg->idiag_meminfo);
422
423 idiagnl_meminfo_get(minfo);
424 msg->idiag_meminfo = minfo;
425 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
426}
427
428struct idiagnl_vegasinfo *idiagnl_msg_get_vegasinfo(const struct idiagnl_msg *msg)
429{
430 return msg->idiag_vegasinfo;
431}
432
433void idiagnl_msg_set_vegasinfo(struct idiagnl_msg *msg, struct idiagnl_vegasinfo *vinfo)
434{
435 if (msg->idiag_vegasinfo)
436 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
437
438 idiagnl_vegasinfo_get(vinfo);
439 msg->idiag_vegasinfo = vinfo;
440 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
441}
442
443struct tcp_info idiagnl_msg_get_tcpinfo(const struct idiagnl_msg *msg)
444{
445 return msg->idiag_tcpinfo;
446}
447
448void idiagnl_msg_set_tcpinfo(struct idiagnl_msg *msg, struct tcp_info *tinfo)
449{
450 memcpy(&msg->idiag_tcpinfo, tinfo, sizeof(struct tcp_info));
451 msg->ce_mask |= IDIAGNL_ATTR_TCPINFO;
452}
453
454/** @} */
455
456static void idiag_msg_dump_line(struct nl_object *a, struct nl_dump_params *p)
457{
458 struct idiagnl_msg *msg = (struct idiagnl_msg *) a;
459 char buf[64] = { 0 };
460
461 nl_dump_line(p, "family: %s ", nl_af2str(msg->idiag_family, buf, sizeof(buf)));
462 nl_dump(p, "src: %s:%d ", nl_addr2str(msg->idiag_src, buf, sizeof(buf)),
463 ntohs(msg->idiag_sport));
464 nl_dump(p, "dst: %s:%d ", nl_addr2str(msg->idiag_dst, buf, sizeof(buf)),
465 ntohs(msg->idiag_dport));
466 nl_dump(p, "iif: %d ", msg->idiag_ifindex);
467 nl_dump(p, "\n");
468}
469
470static void idiag_msg_dump_details(struct nl_object *a, struct nl_dump_params *p)
471{
472 struct idiagnl_msg *msg = (struct idiagnl_msg *) a;
473 char buf[64], buf2[64];
474
475 nl_dump(p, "\nfamily: %s\n", nl_af2str(msg->idiag_family, buf, sizeof(buf)));
476 nl_dump(p, "state: %s\n",
477 idiagnl_state2str(msg->idiag_state, buf, sizeof(buf)));
478 nl_dump(p, "timer (%s, %s, retransmits: %d)\n",
479 idiagnl_timer2str(msg->idiag_timer, buf, sizeof(buf)),
480 nl_msec2str(msg->idiag_expires, buf2, sizeof(buf2)),
481 msg->idiag_retrans);
482
483 nl_dump(p, "source: %s:%d\n", nl_addr2str(msg->idiag_src, buf, sizeof(buf)),
484 ntohs(msg->idiag_sport));
485 nl_dump(p, "destination: %s:%d\n", nl_addr2str(msg->idiag_dst, buf, sizeof(buf)),
486 ntohs(msg->idiag_dport));
487
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",
494 idiagnl_shutdown2str(msg->idiag_shutdown,
495 buf, sizeof(buf)));
496 }
497
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 : "");
501}
502
503static void idiag_msg_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
504{
505 struct idiagnl_msg *msg = (struct idiagnl_msg *) obj;
506 char buf[64];
507
508 idiag_msg_dump_details(obj, p);
509
510 nl_dump(p, "tcp info: [\n");
511 nl_dump(p, "\tsocket state: %s\n",
512 idiagnl_state2str(msg->idiag_tcpinfo.tcpi_state,
513 buf, sizeof(buf)));
514 nl_dump(p, "\ttcp state: %s\n",
515 idiagnl_tcpstate2str(msg->idiag_tcpinfo.tcpi_ca_state,
516 buf, sizeof(buf)));
517 nl_dump(p, "\tretransmits: %d\n",
518 msg->idiag_tcpinfo.tcpi_retransmits);
519 nl_dump(p, "\tprobes: %d\n",
520 msg->idiag_tcpinfo.tcpi_probes);
521 nl_dump(p, "\tbackoff: %d\n",
522 msg->idiag_tcpinfo.tcpi_backoff);
523 nl_dump(p, "\toptions: %s\n",
524 idiagnl_tcpopts2str(msg->idiag_tcpinfo.tcpi_options,
525 buf, sizeof(buf)));
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);
530 nl_dump(p, "\tsnd_mss: %s\n", nl_size2str(msg->idiag_tcpinfo.tcpi_snd_mss,
531 buf, sizeof(buf)));
532 nl_dump(p, "\trcv_mss: %s\n", nl_size2str(msg->idiag_tcpinfo.tcpi_rcv_mss,
533 buf, sizeof(buf)));
534 nl_dump(p, "\tunacked: %d\n", msg->idiag_tcpinfo.tcpi_unacked);
535 nl_dump(p, "\tsacked: %d\n", msg->idiag_tcpinfo.tcpi_sacked);
536
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);
540 nl_dump(p, "\tfackets: %d\n",
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,
544 sizeof(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,
549 sizeof(buf)));
550 nl_dump(p, "\tlast ack recv: %s\n",
551 nl_msec2str(msg->idiag_tcpinfo.tcpi_last_ack_recv, buf,
552 sizeof(buf)));
553 nl_dump(p, "\tpath mtu: %s\n",
554 nl_size2str(msg->idiag_tcpinfo.tcpi_pmtu, buf,
555 sizeof(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,
564 sizeof(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",
568 nl_size2str(msg->idiag_tcpinfo.tcpi_advmss, buf,
569 sizeof(buf)));
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,
576 sizeof(buf)));
577 nl_dump(p, "\ttotal retransmits: %d\n",
578 msg->idiag_tcpinfo.tcpi_total_retrans);
579 nl_dump(p, "]\n");
580
581 if (msg->idiag_meminfo) {
582 nl_dump(p, "meminfo: [\n");
583 nl_dump(p, "\trmem: %s\n",
584 nl_size2str(msg->idiag_meminfo->idiag_rmem,
585 buf,
586 sizeof(buf)));
587 nl_dump(p, "\twmem: %s\n",
588 nl_size2str(msg->idiag_meminfo->idiag_wmem,
589 buf,
590 sizeof(buf)));
591 nl_dump(p, "\tfmem: %s\n",
592 nl_size2str(msg->idiag_meminfo->idiag_fmem,
593 buf,
594 sizeof(buf)));
595 nl_dump(p, "\ttmem: %s\n",
596 nl_size2str(msg->idiag_meminfo->idiag_tmem,
597 buf,
598 sizeof(buf)));
599 nl_dump(p, "]\n");
600 }
601
602 if (msg->idiag_vegasinfo) {
603 nl_dump(p, "vegasinfo: [\n");
604 nl_dump(p, "\tvegas enabled: %d\n",
605 msg->idiag_vegasinfo->tcpv_enabled);
606 if (msg->idiag_vegasinfo->tcpv_enabled) {
607 nl_dump(p, "\trtt cnt: %d",
608 msg->idiag_vegasinfo->tcpv_rttcnt);
609 nl_dump(p, "\trtt (propagation delay): %d",
610 msg->idiag_vegasinfo->tcpv_rtt);
611 nl_dump(p, "\tmin rtt: %d",
612 msg->idiag_vegasinfo->tcpv_minrtt);
613 }
614 nl_dump(p, "]\n");
615 }
616
617 if (msg->ce_mask & IDIAGNL_ATTR_MEMINFO) {
618 nl_dump(p, "skmeminfo: [\n");
619 nl_dump(p, "\trmem alloc: %d\n",
620 msg->idiag_skmeminfo[SK_MEMINFO_RMEM_ALLOC]);
621 nl_dump(p, "\trcv buf: %s\n",
622 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_RCVBUF],
623 buf, sizeof(buf)));
624 nl_dump(p, "\twmem alloc: %d\n",
625 msg->idiag_skmeminfo[SK_MEMINFO_WMEM_ALLOC]);
626 nl_dump(p, "\tsnd buf: %s\n",
627 nl_size2str(msg->idiag_skmeminfo[SK_MEMINFO_SNDBUF],
628 buf, sizeof(buf)));
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],
633 buf, sizeof(buf)));
634 nl_dump(p, "\topt mem: %d\n",
635 msg->idiag_skmeminfo[SK_MEMINFO_OPTMEM]);
636 nl_dump(p, "\tbacklog: %d\n",
637 msg->idiag_skmeminfo[SK_MEMINFO_BACKLOG]);
638 nl_dump(p, "]\n\n");
639 }
640}
641
642static void idiagnl_msg_free(struct nl_object *a)
643{
644 struct idiagnl_msg *msg = (struct idiagnl_msg *) a;
645 if (a == NULL)
646 return;
647
648 free(msg->idiag_cong);
649 nl_addr_put(msg->idiag_src);
650 nl_addr_put(msg->idiag_dst);
651 idiagnl_meminfo_put(msg->idiag_meminfo);
652 idiagnl_vegasinfo_put(msg->idiag_vegasinfo);
653}
654
655static int idiagnl_msg_clone(struct nl_object *_dst, struct nl_object *_src)
656{
657 struct idiagnl_msg *dst = (struct idiagnl_msg *) _dst;
658 struct idiagnl_msg *src = (struct idiagnl_msg *) _src;
659
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 |
666 IDIAGNL_ATTR_SRC |
667 IDIAGNL_ATTR_DST |
668 IDIAGNL_ATTR_MEMINFO |
669 IDIAGNL_ATTR_VEGASINFO);
670
671 if (src->idiag_cong) {
672 if (!(dst->idiag_cong = strdup(src->idiag_cong)))
673 return -NLE_NOMEM;
674 dst->ce_mask |= IDIAGNL_ATTR_CONG;
675 }
676
677 if (src->idiag_src) {
678 if (!(dst->idiag_src = nl_addr_clone(src->idiag_src)))
679 return -NLE_NOMEM;
680 dst->ce_mask |= IDIAGNL_ATTR_SRC;
681 }
682
683 if (src->idiag_dst) {
684 if (!(dst->idiag_dst = nl_addr_clone(src->idiag_dst)))
685 return -NLE_NOMEM;
686 dst->ce_mask |= IDIAGNL_ATTR_DST;
687 }
688
689 if (src->idiag_meminfo) {
690 if (!(dst->idiag_meminfo = (struct idiagnl_meminfo *) nl_object_clone((struct nl_object *) src->idiag_meminfo)))
691 return -NLE_NOMEM;
692 dst->ce_mask |= IDIAGNL_ATTR_MEMINFO;
693 }
694
695 if (src->idiag_vegasinfo) {
696 if (!(dst->idiag_vegasinfo = (struct idiagnl_vegasinfo *) nl_object_clone((struct nl_object *) src->idiag_vegasinfo)))
697 return -NLE_NOMEM;
698 dst->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
699 }
700
701 return 0;
702}
703
704static struct nla_policy ext_policy[INET_DIAG_MAX+1] = {
705 [INET_DIAG_MEMINFO] = { .minlen = sizeof(struct inet_diag_meminfo) },
706 [INET_DIAG_INFO] = { .minlen = sizeof(struct tcp_info) },
707 [INET_DIAG_VEGASINFO] = { .minlen = sizeof(struct tcpvegas_info) },
708 [INET_DIAG_CONG] = { .type = NLA_STRING },
709 [INET_DIAG_TOS] = { .type = NLA_U8 },
710 [INET_DIAG_TCLASS] = { .type = NLA_U8 },
711 /* Older kernel doesn't have SK_MEMINFO_BACKLOG */
712 [INET_DIAG_SKMEMINFO] = { .minlen = (sizeof(uint32_t) * (SK_MEMINFO_OPTMEM + 1)) },
713 [INET_DIAG_SHUTDOWN] = { .type = NLA_U8 },
714};
715
716int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result)
717{
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];
722 int err = 0;
723
724 msg = idiagnl_msg_alloc();
725 if (!msg)
726 goto errout_nomem;
727
728 err = nlmsg_parse(nlh, sizeof(struct inet_diag_msg), tb, INET_DIAG_MAX,
729 ext_policy);
730 if (err < 0)
731 goto errout;
732
733 raw_msg = nlmsg_data(nlh);
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;
746
747 msg->ce_mask = (IDIAGNL_ATTR_FAMILY |
748 IDIAGNL_ATTR_STATE |
749 IDIAGNL_ATTR_TIMER |
750 IDIAGNL_ATTR_RETRANS |
751 IDIAGNL_ATTR_EXPIRES |
752 IDIAGNL_ATTR_RQUEUE |
753 IDIAGNL_ATTR_WQUEUE |
754 IDIAGNL_ATTR_UID |
755 IDIAGNL_ATTR_INODE |
756 IDIAGNL_ATTR_SPORT |
757 IDIAGNL_ATTR_DPORT |
758 IDIAGNL_ATTR_IFINDEX);
759
760 dst = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst,
761 sizeof(raw_msg->id.idiag_dst));
762 if (!dst)
763 goto errout_nomem;
764
765 err = idiagnl_msg_set_dst(msg, dst);
766 if (err < 0)
767 goto errout;
768
769 nl_addr_put(dst);
770
771 src = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src,
772 sizeof(raw_msg->id.idiag_src));
773 if (!src)
774 goto errout_nomem;
775
776 err = idiagnl_msg_set_src(msg, src);
777 if (err < 0)
778 goto errout;
779
780 nl_addr_put(src);
781
782 if (tb[INET_DIAG_TOS]) {
783 msg->idiag_tos = nla_get_u8(tb[INET_DIAG_TOS]);
784 msg->ce_mask |= IDIAGNL_ATTR_TOS;
785 }
786
787 if (tb[INET_DIAG_TCLASS]) {
788 msg->idiag_tclass = nla_get_u8(tb[INET_DIAG_TCLASS]);
789 msg->ce_mask |= IDIAGNL_ATTR_TCLASS;
790 }
791
792 if (tb[INET_DIAG_SHUTDOWN]) {
793 msg->idiag_shutdown = nla_get_u8(tb[INET_DIAG_SHUTDOWN]);
794 msg->ce_mask |= IDIAGNL_ATTR_SHUTDOWN;
795 }
796
797 if (tb[INET_DIAG_CONG]) {
798 msg->idiag_cong = nla_strdup(tb[INET_DIAG_CONG]);
799 msg->ce_mask |= IDIAGNL_ATTR_CONG;
800 }
801
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;
806 }
807
808 if (tb[INET_DIAG_MEMINFO]) {
809 struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc();
810 struct inet_diag_meminfo *raw_minfo = NULL;
811
812 if (!minfo)
813 goto errout_nomem;
814
815 raw_minfo = (struct inet_diag_meminfo *)
816 nla_data(tb[INET_DIAG_MEMINFO]);
817
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);
822
823 msg->idiag_meminfo = minfo;
824 msg->ce_mask |= IDIAGNL_ATTR_MEMINFO;
825 }
826
827 if (tb[INET_DIAG_VEGASINFO]) {
828 struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc();
829 struct tcpvegas_info *raw_vinfo = NULL;
830
831 if (!vinfo)
832 goto errout_nomem;
833
834 raw_vinfo = (struct tcpvegas_info *)
835 nla_data(tb[INET_DIAG_VEGASINFO]);
836
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);
841
842 msg->idiag_vegasinfo = vinfo;
843 msg->ce_mask |= IDIAGNL_ATTR_VEGASINFO;
844 }
845
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;
850 }
851
852 *result = msg;
853 return 0;
854
855errout:
856 idiagnl_msg_put(msg);
857 return err;
858
859errout_nomem:
860 err = -NLE_NOMEM;
861 goto errout;
862}
863
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),
887};
888
889static char *_idiagnl_attrs2str(int attrs, char *buf, size_t len)
890{
891 return __flags2str(attrs, buf, len, idiagnl_attrs,
892 ARRAY_SIZE(idiagnl_attrs));
893}
894
895static uint64_t idiagnl_compare(struct nl_object *_a, struct nl_object *_b,
896 uint64_t attrs, int flags)
897{
898 struct idiagnl_msg *a = (struct idiagnl_msg *) _a;
899 struct idiagnl_msg *b = (struct idiagnl_msg *) _b;
900 uint64_t diff = 0;
901
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,
911 nl_addr_cmp(a->idiag_src, b->idiag_src));
912 diff |= _DIFF(IDIAGNL_ATTR_DST,
913 nl_addr_cmp(a->idiag_dst, b->idiag_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,
928 nl_object_diff((struct nl_object *)a->idiag_meminfo,
929 (struct nl_object *)b->idiag_meminfo));
930 diff |= _DIFF(IDIAGNL_ATTR_VEGASINFO,
931 nl_object_diff((struct nl_object *)a->idiag_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)));
939#undef _DIFF
940
941 return diff;
942}
943
944static void idiagnl_keygen(struct nl_object *obj, uint32_t *hashkey,
945 uint32_t table_sz)
946{
947 struct idiagnl_msg *msg = (struct idiagnl_msg *)obj;
948 unsigned int key_sz;
949 struct idiagnl_hash_key {
950 uint8_t family;
951 uint32_t src_hash;
952 uint32_t dst_hash;
953 uint16_t sport;
954 uint16_t dport;
955 } _nl_packed key;
956
957 key_sz = sizeof(key);
958 key.family = msg->idiag_family;
959 key.src_hash = 0;
960 key.dst_hash = 0;
961 key.sport = msg->idiag_sport;
962 key.dport = msg->idiag_dport;
963
964 if (msg->idiag_src) {
965 key.src_hash = nl_hash (nl_addr_get_binary_addr(msg->idiag_src),
966 nl_addr_get_len(msg->idiag_src), 0);
967 }
968 if (msg->idiag_dst) {
969 key.dst_hash = nl_hash (nl_addr_get_binary_addr(msg->idiag_dst),
970 nl_addr_get_len(msg->idiag_dst), 0);
971 }
972
973 *hashkey = nl_hash(&key, key_sz, 0) % table_sz;
974
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);
977
978 return;
979}
980
981/** @cond SKIP */
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,
987 .oo_dump = {
988 [NL_DUMP_LINE] = idiag_msg_dump_line,
989 [NL_DUMP_DETAILS] = idiag_msg_dump_details,
990 [NL_DUMP_STATS] = idiag_msg_dump_stats,
991 },
992 .oo_compare = idiagnl_compare,
993 .oo_keygen = idiagnl_keygen,
994 .oo_attrs2str = _idiagnl_attrs2str,
995 .oo_id_attrs = (IDIAGNL_ATTR_FAMILY |
996 IDIAGNL_ATTR_SRC |
997 IDIAGNL_ATTR_DST |
998 IDIAGNL_ATTR_SPORT |
999 IDIAGNL_ATTR_DPORT),
1000};
1001/** @endcond */
1002
1003/** @} */
nl_addr_get
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition addr.c:525
nl_addr_build
struct nl_addr * nl_addr_build(int family, const void *buf, size_t size)
Allocate abstract address based on a binary address.
Definition addr.c:216
nl_addr_get_binary_addr
void * nl_addr_get_binary_addr(const struct nl_addr *addr)
Get binary address of abstract address object.
Definition addr.c:943
nl_addr_cmp
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition addr.c:587
nl_addr_clone
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition addr.c:495
nl_addr2str
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition addr.c:1001
nl_addr_get_len
unsigned int nl_addr_get_len(const struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition addr.c:955
nl_addr_put
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition addr.c:541
nla_data
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
nla_get_u8
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:614
nla_memcpy
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:355
NLA_STRING
@ NLA_STRING
NUL terminated character string.
Definition attr.h:39
NLA_U8
@ NLA_U8
8 bit integer
Definition attr.h:35
nl_cache_mngt_unregister
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition cache_mngt.c:287
nl_cache_mngt_register
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition cache_mngt.c:252
nl_cache_refill
int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
Definition cache.c:1043
nl_cache_alloc
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.
Definition cache.c:185
idiagnl_timer2str
char * idiagnl_timer2str(int timer, char *buf, size_t len)
Convert inet diag timer types to strings.
Definition idiag.c:142
idiagnl_shutdown2str
char * idiagnl_shutdown2str(uint8_t shutdown, char *buf, size_t len)
Convert shutdown state to string.
Definition idiag.c:259
idiagnl_state2str
char * idiagnl_state2str(int state, char *buf, size_t len)
Convert inet diag socket states to strings.
Definition idiag.c:107
idiagnl_send_simple
int idiagnl_send_simple(struct nl_sock *sk, int flags, uint8_t family, uint16_t states, uint16_t ext)
Send trivial idiag netlink message.
Definition idiag.c:62
idiagnl_tcpstate2str
char * idiagnl_tcpstate2str(uint8_t state, char *buf, size_t len)
Convert inetdiag tcp states to strings.
Definition idiag.c:223
idiagnl_tcpopts2str
char * idiagnl_tcpopts2str(uint8_t attrs, char *buf, size_t len)
Convert TCP option attributes to string.
Definition idiag.c:245
idiagnl_msg_alloc_cache
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.
Definition idiag_msg_obj.c:174
nlmsg_data
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition msg.c:108
nlmsg_parse
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
Definition msg.c:219
nl_object_diff
uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
Compute 32-bit bitmask representing difference in attribute values.
Definition object.c:395
nl_object_clone
struct nl_object * nl_object_clone(struct nl_object *obj)
Allocate a new object and copy all data from an existing object.
Definition object.c:111
nl_object_put
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition object.c:221
nl_object_get
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition object.c:210
nl_object_alloc
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition object.c:55
nl_size2str
char * nl_size2str(const size_t size, char *buf, const size_t len)
Convert a size toa character string.
Definition utils.c:411
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
nl_msec2str
char * nl_msec2str(uint64_t msec, char *buf, size_t len)
Convert milliseconds to a character string.
Definition utils.c:648
NL_DUMP_STATS
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition types.h:22
NL_DUMP_LINE
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
NL_DUMP_DETAILS
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
idiagnl_meminfo
Definition nl-idiag.h:12
idiagnl_vegasinfo
Definition nl-idiag.h:21
nl_dump_params
Dumping parameters.
Definition types.h:32
nla_policy
Attribute validation policy.
Definition attr.h:66