liyujie
2025-08-28 786ff4f4ca2374bdd9177f2e24b503d43e7a3b93
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <netlink/cli/utils.h>
#include <linux/taskstats.h>
 
static struct nla_policy attr_policy[TASKSTATS_TYPE_MAX+1] = {
   [TASKSTATS_TYPE_PID]    = { .type = NLA_U32 },
   [TASKSTATS_TYPE_TGID]    = { .type = NLA_U32 },
   [TASKSTATS_TYPE_STATS]    = { .minlen = sizeof(struct taskstats) },
   [TASKSTATS_TYPE_AGGR_PID] = { .type = NLA_NESTED },
   [TASKSTATS_TYPE_AGGR_TGID] = { .type = NLA_NESTED },
};
 
 
static int parse_cmd_new(struct nl_cache_ops *unused, struct genl_cmd *cmd,
            struct genl_info *info, void *arg)
{
   struct nlattr *attrs[TASKSTATS_TYPE_MAX+1];
   struct nlattr *nested;
   int err;
 
   if (info->attrs[TASKSTATS_TYPE_AGGR_PID])
       nested = info->attrs[TASKSTATS_TYPE_AGGR_PID];
   else if (info->attrs[TASKSTATS_TYPE_AGGR_TGID])
       nested = info->attrs[TASKSTATS_TYPE_AGGR_TGID];
   else {
       fprintf(stderr, "Invalid taskstats message: Unable to find "
               "nested attribute/\n");
       return NL_SKIP;
   }
 
   err = nla_parse_nested(attrs, TASKSTATS_TYPE_MAX, nested, attr_policy);
   if (err < 0) {
       nl_perror(err, "Error while parsing generic netlink message");
       return err;
   }
 
 
   if (attrs[TASKSTATS_TYPE_STATS]) {
       struct taskstats *stats = nla_data(attrs[TASKSTATS_TYPE_STATS]);
 
       printf("%s pid %u uid %u gid %u parent %u\n",
              stats->ac_comm, stats->ac_pid, stats->ac_uid,
              stats->ac_gid, stats->ac_ppid);
   }
 
   return 0;
}
 
static int parse_cb(struct nl_msg *msg, void *arg)
{
   return genl_handle_msg(msg, NULL);
}
 
static struct genl_cmd cmds[] = {
   {
       .c_id        = TASKSTATS_CMD_NEW,
       .c_name        = "taskstats_new()",
       .c_maxattr    = TASKSTATS_TYPE_MAX,
       .c_attr_policy    = attr_policy,
       .c_msg_parser    = &parse_cmd_new,
   },
};
 
#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
 
static struct genl_ops ops = {
   .o_name = TASKSTATS_GENL_NAME,
   .o_cmds = cmds,
   .o_ncmds = ARRAY_SIZE(cmds),
};
 
int main(int argc, char *argv[])
{
   struct nl_sock *sock;
   struct nl_msg *msg;
   void *hdr;
   int err;
 
   sock = nl_cli_alloc_socket();
   nl_cli_connect(sock, NETLINK_GENERIC);
 
   if ((err = genl_register_family(&ops)) < 0)
       nl_cli_fatal(err, "Unable to register Generic Netlink family");
 
   if ((err = genl_ops_resolve(sock, &ops)) < 0)
       nl_cli_fatal(err, "Unable to resolve family name");
 
   if (genl_ctrl_resolve(sock, "nlctrl") != GENL_ID_CTRL)
       nl_cli_fatal(NLE_INVAL, "Resolving of \"nlctrl\" failed");
 
   msg = nlmsg_alloc();
   if (msg == NULL)
       nl_cli_fatal(NLE_NOMEM, "Unable to allocate netlink message");
 
   hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ops.o_id,
             0, 0, TASKSTATS_CMD_GET, TASKSTATS_GENL_VERSION);
   if (hdr == NULL)
       nl_cli_fatal(ENOMEM, "Unable to write genl header");
 
   if ((err = nla_put_u32(msg, TASKSTATS_CMD_ATTR_PID, 1)) < 0)
       nl_cli_fatal(err, "Unable to add attribute: %s", nl_geterror(err));
 
   if ((err = nl_send_auto_complete(sock, msg)) < 0)
       nl_cli_fatal(err, "Unable to send message: %s", nl_geterror(err));
 
   nlmsg_free(msg);
 
   if ((err = nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM,
           parse_cb, NULL)) < 0)
       nl_cli_fatal(err, "Unable to modify valid message callback");
 
   if ((err = nl_recvmsgs_default(sock)) < 0)
       nl_cli_fatal(err, "Unable to receive message: %s", nl_geterror(err));
 
   nl_close(sock);
   nl_socket_free(sock);
 
   return 0;
}