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