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