test-genl.c 3.1 KB

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