static int link_mon_summary_cb(const struct nlmsghdr *nlh, void *data) { struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {}; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_MON]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs); open_json_object(NULL); print_string(PRINT_ANY, "bearer", "\nbearer %s\n", mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME])); print_uint(PRINT_ANY, "table_generation", " table_generation %u\n", mnl_attr_get_u32(attrs[TIPC_NLA_MON_LISTGEN])); print_uint(PRINT_ANY, "cluster_size", " cluster_size %u\n", mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT])); print_string(PRINT_ANY, "algorithm", " algorithm %s\n", attrs[TIPC_NLA_MON_ACTIVE] ? "overlapping-ring" : "full-mesh"); close_json_object(); return MNL_CB_OK; }
static int nftnl_expr_lookup_parse(struct nftnl_expr *e, struct nlattr *attr) { struct nftnl_expr_lookup *lookup = nftnl_expr_data(e); struct nlattr *tb[NFTA_LOOKUP_MAX+1] = {}; int ret = 0; if (mnl_attr_parse_nested(attr, nftnl_expr_lookup_cb, tb) < 0) return -1; if (tb[NFTA_LOOKUP_SREG]) { lookup->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_LOOKUP_SREG])); e->flags |= (1 << NFTNL_EXPR_LOOKUP_SREG); } if (tb[NFTA_LOOKUP_DREG]) { lookup->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_LOOKUP_DREG])); e->flags |= (1 << NFTNL_EXPR_LOOKUP_DREG); } if (tb[NFTA_LOOKUP_SET]) { strcpy(lookup->set_name, mnl_attr_get_str(tb[NFTA_LOOKUP_SET])); e->flags |= (1 << NFTNL_EXPR_LOOKUP_SET); } if (tb[NFTA_LOOKUP_SET_ID]) { lookup->set_id = ntohl(mnl_attr_get_u32(tb[NFTA_LOOKUP_SET_ID])); e->flags |= (1 << NFTNL_EXPR_LOOKUP_SET_ID); } return ret; }
static int link_stat_show_cb(const struct nlmsghdr *nlh, void *data) { const char *name; const char *link = data; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {}; struct nlattr *prop[TIPC_NLA_PROP_MAX + 1] = {}; struct nlattr *stats[TIPC_NLA_STATS_MAX + 1] = {}; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_LINK]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs); if (!attrs[TIPC_NLA_LINK_NAME] || !attrs[TIPC_NLA_LINK_PROP] || !attrs[TIPC_NLA_LINK_STATS]) return MNL_CB_ERROR; mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_PROP], parse_attrs, prop); mnl_attr_parse_nested(attrs[TIPC_NLA_LINK_STATS], parse_attrs, stats); name = mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]); /* If a link is passed, skip all but that link */ if (link && (strcmp(name, link) != 0)) return MNL_CB_OK; if (attrs[TIPC_NLA_LINK_BROADCAST]) { return _show_bc_link_stat(name, prop, stats); } return _show_link_stat(name, attrs, prop, stats); }
static int res_print_summary(struct rd *rd, struct nlattr **tb) { struct nlattr *nla_table = tb[RDMA_NLDEV_ATTR_RES_SUMMARY]; struct nlattr *nla_entry; const char *name; uint64_t curr; int err; mnl_attr_for_each_nested(nla_entry, nla_table) { struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; char json_name[32]; err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (err != MNL_CB_OK) return -EINVAL; if (!nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME] || !nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR]) { return -EINVAL; } name = mnl_attr_get_str(nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME]); curr = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR]); if (rd->json_output) { snprintf(json_name, 32, "%s", name); jsonw_lluint_field(rd->jw, json_name, curr); } else { pr_out("%s %"PRId64 " ", name, curr); } } return 0; }
static int nfct_parse_helper(const struct nlattr *attr, struct nf_conntrack *ct) { struct nlattr *tb[CTA_HELP_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_helper_attr_cb, tb) < 0) return -1; if (!tb[CTA_HELP_NAME]) return 0; strncpy(ct->helper_name, mnl_attr_get_str(tb[CTA_HELP_NAME]), NFCT_HELPER_NAME_MAX); ct->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; set_bit(ATTR_HELPER_NAME, ct->head.set); if (!tb[CTA_HELP_INFO]) return 0; ct->helper_info_len = mnl_attr_get_payload_len(tb[CTA_HELP_INFO]); ct->helper_info = calloc(1, ct->helper_info_len); if (ct->helper_info == NULL) return -1; memcpy(ct->helper_info, mnl_attr_get_payload(tb[CTA_HELP_INFO]), ct->helper_info_len); set_bit(ATTR_HELPER_INFO, ct->head.set); return 0; }
int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct nlattr *nla_table, *nla_entry; struct rd *rd = data; int ret = MNL_CB_OK; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_PD]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); nla_table = tb[RDMA_NLDEV_ATTR_RES_PD]; mnl_attr_for_each_nested(nla_entry, nla_table) { struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; ret = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (ret != MNL_CB_OK) break; ret = res_pd_line(rd, name, idx, nla_line); if (ret != MNL_CB_OK) break; } return ret; }
static int link_mon_list_cb(const struct nlmsghdr *nlh, void *data) { struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_MON_MAX + 1] = {}; char *req_bearer = data; const char *bname; const char title[] = "node status monitored generation applied_node_status [non_applied_node:status]"; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_MON]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_MON], parse_attrs, attrs); bname = mnl_attr_get_str(attrs[TIPC_NLA_MON_BEARER_NAME]); if (*req_bearer && (strcmp(req_bearer, bname) != 0)) return MNL_CB_OK; open_json_object(NULL); print_string(PRINT_ANY, "bearer", "\nbearer %s\n", bname); print_string(PRINT_FP, NULL, "%s\n", title); open_json_array(PRINT_JSON, bname); if (mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEERCNT])) link_mon_peer_list(mnl_attr_get_u32(attrs[TIPC_NLA_MON_REF])); close_json_array(PRINT_JSON, bname); close_json_object(); return MNL_CB_OK; }
static int res_no_args_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_SUMMARY]) return MNL_CB_ERROR; idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); if (rd->json_output) { jsonw_uint_field(rd->jw, "ifindex", idx); jsonw_string_field(rd->jw, "ifname", name); } else { pr_out("%u: %s: ", idx, name); } res_print_summary(rd, tb); if (!rd->json_output) pr_out("\n"); return MNL_CB_OK; }
int nfexp_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_expect *exp) { struct nlattr *tb[CTA_EXPECT_MAX+1] = {}; struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(struct nfgenmsg), nlmsg_parse_expection_attr_cb, tb); if (tb[CTA_EXPECT_MASTER]) { exp->expected.orig.l3protonum = nfg->nfgen_family; set_bit(ATTR_ORIG_L3PROTO, exp->expected.set); nfct_parse_tuple(tb[CTA_EXPECT_MASTER], &exp->master.orig, __DIR_ORIG, exp->master.set); set_bit(ATTR_EXP_MASTER, exp->set); } if (tb[CTA_EXPECT_TUPLE]) { exp->mask.orig.l3protonum = nfg->nfgen_family; set_bit(ATTR_ORIG_L3PROTO, exp->mask.set); nfct_parse_tuple(tb[CTA_EXPECT_TUPLE], &exp->expected.orig, __DIR_ORIG, exp->expected.set); set_bit(ATTR_EXP_EXPECTED, exp->set); } if (tb[CTA_EXPECT_MASK]) { exp->master.orig.l3protonum = nfg->nfgen_family; set_bit(ATTR_ORIG_L3PROTO, exp->master.set); nfct_parse_tuple(tb[CTA_EXPECT_MASK], &exp->mask.orig, __DIR_ORIG, exp->mask.set); set_bit(ATTR_EXP_MASK, exp->set); } if (tb[CTA_EXPECT_TIMEOUT]) { exp->timeout = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_TIMEOUT])); set_bit(ATTR_EXP_TIMEOUT, exp->set); } if (tb[CTA_EXPECT_ZONE]) { exp->zone = ntohs(mnl_attr_get_u16(tb[CTA_EXPECT_ZONE])); set_bit(ATTR_EXP_ZONE, exp->set); } if (tb[CTA_EXPECT_FLAGS]) { exp->flags = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_FLAGS])); set_bit(ATTR_EXP_FLAGS, exp->set); } if (tb[CTA_EXPECT_HELP_NAME]) { strncpy(exp->helper_name, mnl_attr_get_str(tb[CTA_EXPECT_HELP_NAME]), NFCT_HELPER_NAME_MAX); set_bit(ATTR_EXP_HELPER_NAME, exp->set); } return 0; }
static int link_list_cb(const struct nlmsghdr *nlh, void *data) { struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *info[TIPC_NLA_MAX + 1] = {}; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1] = {}; mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); if (!info[TIPC_NLA_LINK]) return MNL_CB_ERROR; mnl_attr_parse_nested(info[TIPC_NLA_LINK], parse_attrs, attrs); if (!attrs[TIPC_NLA_LINK_NAME]) return MNL_CB_ERROR; print_string(PRINT_FP, NULL, "%s: ", mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME])); if (attrs[TIPC_NLA_LINK_UP]) print_string(PRINT_ANY, mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]),"%s\n", "up"); else print_string(PRINT_ANY, mnl_attr_get_str(attrs[TIPC_NLA_LINK_NAME]), "%s\n", "down"); return MNL_CB_OK; }
int res_pd_idx_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); return res_pd_line(rd, name, idx, tb); }
static void parse_genl_mc_grps(struct nlattr *nested) { struct nlattr *pos; mnl_attr_for_each_nested(pos, nested) { struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1] = {}; mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb); if (tb[CTRL_ATTR_MCAST_GRP_ID]) { printf("id-0x%x ", mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID])); } if (tb[CTRL_ATTR_MCAST_GRP_NAME]) { printf("name: %s ", mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME])); } printf("\n"); } }
/** * nfacct_nlmsg_parse_payload - set accounting object attributes from message * \param nlh: netlink message that you want to use to add the payload. * \param nfacct: pointer to a accounting object * * This function returns -1 in case that some mandatory attributes are * missing. On sucess, it returns 0. */ int nfacct_nlmsg_parse_payload(const struct nlmsghdr *nlh, struct nfacct *nfacct) { struct nlattr *tb[NFACCT_MAX+1] = {}; struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(*nfg), nfacct_nlmsg_parse_attr_cb, tb); if (!tb[NFACCT_NAME] && !tb[NFACCT_PKTS] && !tb[NFACCT_BYTES]) return -1; nfacct_attr_set_str(nfacct, NFACCT_ATTR_NAME, mnl_attr_get_str(tb[NFACCT_NAME])); nfacct_attr_set_u64(nfacct, NFACCT_ATTR_PKTS, be64toh(mnl_attr_get_u64(tb[NFACCT_PKTS]))); nfacct_attr_set_u64(nfacct, NFACCT_ATTR_BYTES, be64toh(mnl_attr_get_u64(tb[NFACCT_BYTES]))); return 0; }
static int nft_rule_expr_match_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_match *match = nft_expr_data(e); struct nlattr *tb[NFTA_MATCH_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nft_rule_expr_match_cb, tb) < 0) return -1; if (tb[NFTA_MATCH_NAME]) { snprintf(match->name, XT_EXTENSION_MAXNAMELEN, "%s", mnl_attr_get_str(tb[NFTA_MATCH_NAME])); match->name[XT_EXTENSION_MAXNAMELEN-1] = '\0'; e->flags |= (1 << NFT_EXPR_MT_NAME); } if (tb[NFTA_MATCH_REV]) { match->rev = ntohl(mnl_attr_get_u32(tb[NFTA_MATCH_REV])); e->flags |= (1 << NFT_EXPR_MT_REV); } if (tb[NFTA_MATCH_INFO]) { uint32_t len = mnl_attr_get_payload_len(tb[NFTA_MATCH_INFO]); void *match_data; if (match->data) xfree(match->data); match_data = calloc(1, len); if (match_data == NULL) return -1; memcpy(match_data, mnl_attr_get_payload(tb[NFTA_MATCH_INFO]), len); match->data = match_data; match->data_len = len; e->flags |= (1 << NFT_EXPR_MT_INFO); } return 0; }
static int nftnl_expr_target_parse(struct nftnl_expr *e, struct nlattr *attr) { struct nftnl_expr_target *target = nftnl_expr_data(e); struct nlattr *tb[NFTA_TARGET_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nftnl_expr_target_cb, tb) < 0) return -1; if (tb[NFTA_TARGET_NAME]) { snprintf(target->name, XT_EXTENSION_MAXNAMELEN, "%s", mnl_attr_get_str(tb[NFTA_TARGET_NAME])); target->name[XT_EXTENSION_MAXNAMELEN-1] = '\0'; e->flags |= (1 << NFTNL_EXPR_TG_NAME); } if (tb[NFTA_TARGET_REV]) { target->rev = ntohl(mnl_attr_get_u32(tb[NFTA_TARGET_REV])); e->flags |= (1 << NFTNL_EXPR_TG_REV); } if (tb[NFTA_TARGET_INFO]) { uint32_t len = mnl_attr_get_payload_len(tb[NFTA_TARGET_INFO]); void *target_data; if (target->data) xfree(target->data); target_data = calloc(1, len); if (target_data == NULL) return -1; memcpy(target_data, mnl_attr_get_payload(tb[NFTA_TARGET_INFO]), len); target->data = target_data; target->data_len = len; e->flags |= (1 << NFTNL_EXPR_TG_INFO); } return 0; }
static int log_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[NFULA_MAX+1] = {}; struct nfulnl_msg_packet_hdr *ph = NULL; const char *prefix = NULL; uint32_t mark = 0; mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb); if (tb[NFULA_PACKET_HDR]) ph = mnl_attr_get_payload(tb[NFULA_PACKET_HDR]); if (tb[NFULA_PREFIX]) prefix = mnl_attr_get_str(tb[NFULA_PREFIX]); if (tb[NFULA_MARK]) mark = ntohl(mnl_attr_get_u32(tb[NFULA_MARK])); printf("log received (prefix=\"%s\" hw=0x%04x hook=%u mark=%u)\n", prefix ? prefix : "", ntohs(ph->hw_protocol), ph->hook, mark); return MNL_CB_OK; }
static int nft_rule_expr_log_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_log *log = nft_expr_data(e); struct nlattr *tb[NFTA_LOG_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nft_rule_expr_log_cb, tb) < 0) return -1; if (tb[NFTA_LOG_PREFIX]) { if (log->prefix) xfree(log->prefix); log->prefix = strdup(mnl_attr_get_str(tb[NFTA_LOG_PREFIX])); e->flags |= (1 << NFT_EXPR_LOG_PREFIX); } if (tb[NFTA_LOG_GROUP]) { log->group = ntohs(mnl_attr_get_u16(tb[NFTA_LOG_GROUP])); e->flags |= (1 << NFT_EXPR_LOG_GROUP); } if (tb[NFTA_LOG_SNAPLEN]) { log->snaplen = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_SNAPLEN])); e->flags |= (1 << NFT_EXPR_LOG_SNAPLEN); } if (tb[NFTA_LOG_QTHRESHOLD]) { log->qthreshold = ntohs(mnl_attr_get_u16(tb[NFTA_LOG_QTHRESHOLD])); e->flags |= (1 << NFT_EXPR_LOG_QTHRESHOLD); } if (tb[NFTA_LOG_LEVEL]) { log->level = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_LEVEL])); e->flags |= (1 << NFT_EXPR_LOG_LEVEL); } if (tb[NFTA_LOG_FLAGS]) { log->flags = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_FLAGS])); e->flags |= (1 << NFT_EXPR_LOG_FLAGS); } return 0; }
static void parse_genl_mc_grps(struct nlattr *nested, struct group_info *group_info) { struct nlattr *pos; const char *name; mnl_attr_for_each_nested(pos, nested) { struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX + 1] = {}; mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb); if (!tb[CTRL_ATTR_MCAST_GRP_NAME] || !tb[CTRL_ATTR_MCAST_GRP_ID]) continue; name = mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME]); if (strcmp(name, group_info->name) != 0) continue; group_info->id = mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); group_info->found = true; } }
static int data_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[CTRL_ATTR_MAX+1] = {}; struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); mnl_attr_parse(nlh, sizeof(*genl), data_attr_cb, tb); if (tb[CTRL_ATTR_FAMILY_NAME]) { printf("name=%s\t", mnl_attr_get_str(tb[CTRL_ATTR_FAMILY_NAME])); } if (tb[CTRL_ATTR_FAMILY_ID]) { printf("id=%u\t", mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID])); } if (tb[CTRL_ATTR_VERSION]) { printf("version=%u\t", mnl_attr_get_u32(tb[CTRL_ATTR_VERSION])); } if (tb[CTRL_ATTR_HDRSIZE]) { printf("hdrsize=%u\t", mnl_attr_get_u32(tb[CTRL_ATTR_HDRSIZE])); } if (tb[CTRL_ATTR_MAXATTR]) { printf("maxattr=%u\t", mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR])); } printf("\n"); if (tb[CTRL_ATTR_OPS]) { printf("ops:\n"); parse_genl_family_ops(tb[CTRL_ATTR_OPS]); } if (tb[CTRL_ATTR_MCAST_GROUPS]) { printf("grps:\n"); parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS]); } printf("\n"); return MNL_CB_OK; }
static int data_attr_cb(const struct nlattr *attr, void *data) { /* skip unsupported attribute in user-space */ if (mnl_attr_type_valid(attr, IFLA_MAX) < 0) return MNL_CB_OK; switch(mnl_attr_get_type(attr)) { case IFLA_MTU: if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { perror("mnl_attr_validate"); return MNL_CB_ERROR; } printf("mtu=%d ", mnl_attr_get_u32(attr)); break; case IFLA_IFNAME: if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) { perror("mnl_attr_validate2"); return MNL_CB_ERROR; } printf("name=%s ", mnl_attr_get_str(attr)); break; } return MNL_CB_OK; }
static int data_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[IFLA_MAX+1] = {}; struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh); printf("index=%d type=%d flags=%d family=%d ", ifm->ifi_index, ifm->ifi_type, ifm->ifi_flags, ifm->ifi_family); if (ifm->ifi_flags & IFF_RUNNING) printf("[RUNNING] "); else printf("[NOT RUNNING] "); mnl_attr_parse(nlh, sizeof(*ifm), data_attr_cb, tb); if (tb[IFLA_MTU]) { printf("mtu=%d ", mnl_attr_get_u32(tb[IFLA_MTU])); } if (tb[IFLA_IFNAME]) { printf("name=%s", mnl_attr_get_str(tb[IFLA_IFNAME])); } printf("\n"); return MNL_CB_OK; }
static int log_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[NFULA_MAX+1] = {}; mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb); if (tb[NFULA_PREFIX]) { const char *prefix = mnl_attr_get_str(tb[NFULA_PREFIX]); printf("%s ", prefix); } if (tb[NFULA_IFINDEX_INDEV]) { uint32_t indev = ntohl(mnl_attr_get_u32(tb[NFULA_IFINDEX_INDEV])); char *instr = get_net_device_name_by_index(indev); printf("IN=%s ", instr ? instr : ""); } else { printf("IN= "); } if (tb[NFULA_IFINDEX_OUTDEV]) { uint32_t outdev = ntohl(mnl_attr_get_u32(tb[NFULA_IFINDEX_OUTDEV])); char *outstr = get_net_device_name_by_index(outdev); printf("OUT=%s ", outstr ? outstr : ""); } else { printf("OUT= "); } if (tb[NFULA_PAYLOAD]) { struct iphdr *iph = (struct iphdr *) mnl_attr_get_payload(tb[NFULA_PAYLOAD]); printf("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ", ((unsigned char *)&iph->saddr)[0], ((unsigned char *)&iph->saddr)[1], ((unsigned char *)&iph->saddr)[2], ((unsigned char *)&iph->saddr)[3], ((unsigned char *)&iph->daddr)[0], ((unsigned char *)&iph->daddr)[1], ((unsigned char *)&iph->daddr)[2], ((unsigned char *)&iph->daddr)[3]); printf("LEN=%u ", ntohs(iph->tot_len)); switch(iph->protocol) { case IPPROTO_TCP: { struct tcphdr *th = (struct tcphdr *) ((__u32 *) iph + iph->ihl); printf("PROTO=TCP SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); break; } case IPPROTO_UDP: { struct udphdr *uh = (struct udphdr *) ((__u32 *) iph + iph->ihl); printf("PROTO=UDP SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); break; } case IPPROTO_ICMP: { struct icmphdr *ich = (struct icmphdr *) ((__u32 *) iph + iph->ihl); printf("PROTO=ICMP TYPE=%u CODE=%u ", ich->type, ich->code); break; } default: { printf("PROTO=%u ", iph->protocol); } } } if (tb[NFULA_UID]) { uint32_t uid = ntohl(mnl_attr_get_u32(tb[NFULA_UID])); printf("UID=%u ", uid); } puts(""); return MNL_CB_OK; }
static int res_pd_line(struct rd *rd, const char *name, int idx, struct nlattr **nla_line) { uint32_t local_dma_lkey = 0, unsafe_global_rkey = 0; char *comm = NULL; uint32_t ctxn = 0; uint32_t pid = 0; uint32_t pdn = 0; uint64_t users; if (!nla_line[RDMA_NLDEV_ATTR_RES_USECNT] || (!nla_line[RDMA_NLDEV_ATTR_RES_PID] && !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) { return MNL_CB_ERROR; } if (nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]) local_dma_lkey = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]); users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]); if (rd_is_filtered_attr(rd, "users", users, nla_line[RDMA_NLDEV_ATTR_RES_USECNT])) goto out; if (nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]) unsafe_global_rkey = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]); if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]); comm = get_task_name(pid); } if (rd_is_filtered_attr(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID])) goto out; if (nla_line[RDMA_NLDEV_ATTR_RES_CTXN]) ctxn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CTXN]); if (rd_is_filtered_attr(rd, "ctxn", ctxn, nla_line[RDMA_NLDEV_ATTR_RES_CTXN])) goto out; if (nla_line[RDMA_NLDEV_ATTR_RES_PDN]) pdn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PDN]); if (rd_is_filtered_attr(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN])) goto out; if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) /* discard const from mnl_attr_get_str */ comm = (char *)mnl_attr_get_str( nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]); if (rd->json_output) jsonw_start_array(rd->jw); print_dev(rd, idx, name); res_print_uint(rd, "pdn", pdn, nla_line[RDMA_NLDEV_ATTR_RES_PDN]); print_key(rd, "local_dma_lkey", local_dma_lkey, nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]); res_print_uint(rd, "users", users, nla_line[RDMA_NLDEV_ATTR_RES_USECNT]); print_key(rd, "unsafe_global_rkey", unsafe_global_rkey, nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]); res_print_uint(rd, "ctxn", ctxn, nla_line[RDMA_NLDEV_ATTR_RES_CTXN]); res_print_uint(rd, "pid", pid, nla_line[RDMA_NLDEV_ATTR_RES_PID]); print_comm(rd, comm, nla_line); print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); newline(rd); out: if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) free(comm); return MNL_CB_OK; }
static int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct nlattr *nla_table, *nla_entry; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_QP]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); nla_table = tb[RDMA_NLDEV_ATTR_RES_QP]; mnl_attr_for_each_nested(nla_entry, nla_table) { struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; uint32_t lqpn, rqpn = 0, rq_psn = 0, sq_psn; uint8_t type, state, path_mig_state = 0; uint32_t port = 0, pid = 0; char *comm = NULL; int err; err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (err != MNL_CB_OK) return MNL_CB_ERROR; if (!nla_line[RDMA_NLDEV_ATTR_RES_LQPN] || !nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN] || !nla_line[RDMA_NLDEV_ATTR_RES_TYPE] || !nla_line[RDMA_NLDEV_ATTR_RES_STATE] || (!nla_line[RDMA_NLDEV_ATTR_RES_PID] && !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) { return MNL_CB_ERROR; } if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]) port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]); if (port != rd->port_idx) continue; lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]); if (rd_check_is_filtered(rd, "lqpn", lqpn)) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN]) { rqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQPN]); if (rd_check_is_filtered(rd, "rqpn", rqpn)) continue; } else { if (rd_check_is_key_exist(rd, "rqpn")) continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]) { rq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]); if (rd_check_is_filtered(rd, "rq-psn", rq_psn)) continue; } else { if (rd_check_is_key_exist(rd, "rq-psn")) continue; } sq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]); if (rd_check_is_filtered(rd, "sq-psn", sq_psn)) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]) { path_mig_state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]); if (rd_check_is_string_filtered(rd, "path-mig-state", path_mig_to_str(path_mig_state))) continue; } else { if (rd_check_is_key_exist(rd, "path-mig-state")) continue; } type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]); if (rd_check_is_string_filtered(rd, "type", qp_types_to_str(type))) continue; state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]); if (rd_check_is_string_filtered(rd, "state", qp_states_to_str(state))) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]); comm = get_task_name(pid); } if (rd_check_is_filtered(rd, "pid", pid)) { free(comm); continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) /* discard const from mnl_attr_get_str */ comm = (char *)mnl_attr_get_str(nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]); if (rd->json_output) jsonw_start_array(rd->jw); print_link(rd, idx, name, port, nla_line); print_lqpn(rd, lqpn); print_rqpn(rd, rqpn, nla_line); print_type(rd, type); print_state(rd, state); print_rqpsn(rd, rq_psn, nla_line); print_sqpsn(rd, sq_psn); print_pathmig(rd, path_mig_state, nla_line); print_pid(rd, pid); print_comm(rd, comm, nla_line); if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) free(comm); print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); newline(rd); } return MNL_CB_OK; }
static int data_cb(const struct nlmsghdr * nlh, void * data) { struct nlattr * tb[IFLA_MAX + 1] = {}; struct ifinfomsg * ifm = mnl_nlmsg_get_payload(nlh); char * notification = NULL; const char * interface = NULL; NotifyNotification * netlink = NULL; unsigned int errcount = 0; gboolean res = FALSE; GError * error = NULL; mnl_attr_parse(nlh, sizeof(* ifm), data_attr_cb, tb); interface = mnl_attr_get_str(tb[IFLA_IFNAME]); notification = malloc(strlen(interface) + strlen(NOTIFICATION_TEXT) + 1); // 2* %s is enough for "down", but we need an additional byte for \n sprintf(notification, NOTIFICATION_TEXT, interface, (ifm->ifi_flags & IFF_RUNNING ? "up" : "down")); printf(NOTIFICATION_TEXT_DEBUG, program, interface, ifm->ifi_index, (ifm->ifi_flags & IFF_RUNNING ? "up" : "down")); if (netlinksize < ifm->ifi_index) { netlinkref = realloc(netlinkref, (ifm->ifi_index + 1) * sizeof(size_t)); while(netlinksize < ifm->ifi_index) netlinkref[++netlinksize] = 0; } if (netlinkref[ifm->ifi_index] == 0) { netlink = notify_notification_new("Netlink", notification, (ifm->ifi_flags & IFF_RUNNING ? "network-transmit-receive" : "network-error")); netlinkref[ifm->ifi_index] = (size_t)netlink; } else { netlink = (NotifyNotification *)netlinkref[ifm->ifi_index]; notify_notification_update(netlink, "Netlink", notification, (ifm->ifi_flags & IFF_RUNNING ? "network-transmit-receive" : "network-error")); } notify_notification_set_timeout(netlink, NOTIFICATION_TIMEOUT); notify_notification_set_category(netlink, "Netlink"); notify_notification_set_urgency (netlink, NOTIFY_URGENCY_NORMAL); while(!notify_notification_show(netlink, &error)) { if (errcount > 1) { fprintf(stderr, "%s: Looks like we can not reconnect to notification daemon... Exiting.\n", program); exit(EXIT_FAILURE); } else { g_printerr("%s: Error \"%s\" while trying to show notification. Trying to reconnect.\n", program, error->message); errcount++; g_error_free(error); error = NULL; notify_uninit(); usleep(500 * 1000); if(!notify_init("Udev-Net-Notification")) { fprintf(stderr, "%s: Can't create notify.\n", program); exit(EXIT_FAILURE); } } } errcount = 0; free(notification); return MNL_CB_OK; }
static void multi_link_modify_link(const struct nlmsghdr *nlh, uint32_t probe_pipe, uint8_t unique){ struct ifinfomsg *ifi = mnl_nlmsg_get_payload(nlh); struct nlattr *tb[IFLA_MAX + 1] = {}; uint8_t iface_state = 0; struct multi_link_info *li = NULL; struct multi_link_info_static *li_static = NULL; pthread_attr_t detach_attr; uint8_t wireless_mode = 0; uint8_t *if_name; mnl_attr_parse(nlh, sizeof(*ifi), multi_link_fill_rtattr, tb); if (!tb[IFLA_IFNAME]) { MULTI_DEBUG_PRINT_SYSLOG(stderr, "Missing interface name\n"); return; } if_name = (uint8_t*) mnl_attr_get_str(tb[IFLA_IFNAME]); if (!strncmp(if_name, "veth", 4) || ifi->ifi_type == ARPHRD_VOID || (ifi->ifi_type == ARPHRD_NONE && strncmp(if_name,"wwan", 4)) || ifi->ifi_type == ARPHRD_TUNNEL || ifi->ifi_flags & IFF_LOOPBACK) return; if(tb[IFLA_OPERSTATE]){ iface_state = mnl_attr_get_u8(tb[IFLA_OPERSTATE]); /* Check linux/Documentation/networking/operstates.txt. IFF_RUNNING * wraps both UP and UNKNOWN*/ if (ifi->ifi_flags & IFF_RUNNING){ //IF_OPER_UP == 6, defined in linux/if.h, chaos with includes //if(iface_state == 6){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Interface %s (%u) is RUNNING, " "length %u\n", if_name, ifi->ifi_index, multi_link_num_links); if((wireless_mode = multi_link_check_wlan_mode(if_name))) if(wireless_mode == 6){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Interface %s is monitor, " "ignoring\n", if_name); return; } LIST_FIND_CUSTOM(li, &multi_link_links_2, next, &(ifi->ifi_index), multi_cmp_ifidx); if(li != NULL){ if(li->state == LINK_UP_STATIC_IFF){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Interface %s (idx %u) has " "gone from UP to RUNNING\n", if_name, ifi->ifi_index); li->state = GOT_IP_STATIC; } else MULTI_DEBUG_PRINT_SYSLOG(stderr,"Interface %s (idx %u) has " "already been seen. Ignoring event\n", if_name, ifi->ifi_index); return; } if(multi_link_num_links < MAX_NUM_LINKS){ TAILQ_FIND_CUSTOM(li_static, &multi_shared_static_links, list_ptr, if_name, multi_cmp_devname); if(li_static != NULL){ if(li_static->proto == PROTO_IGNORE){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Ignoring %s\n", if_name); return; } else li = multi_link_create_new_link(if_name, li_static->metric); } else { /* Allocate a new link, add to list and start DHCP */ li = multi_link_create_new_link(if_name, 0); } if (!li) { MULTI_DEBUG_PRINT_SYSLOG(stderr, "Could not create link\n"); return; } //Insert link into link list LIST_INSERT_HEAD(&multi_link_links_2, li, next); ++multi_link_num_links; /* Add as a case here! The check for point to point */ if(li_static != NULL && li_static->proto == PROTO_STATIC){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Link %s found in static list\n", if_name); li->state = GOT_IP_STATIC; li->cfg = li_static->cfg_static; } else if (ifi->ifi_type == ARPHRD_PPP){ /* PPP will be dealt with separatley, since they get the IP * remotely by themself */ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Link %s (%u) is PPP! state " "%u %u\n", if_name, ifi->ifi_index, iface_state, IFF_RUNNING); li->state = LINK_DOWN_PPP; multi_link_get_iface_info(li); if(li->state != GOT_IP_PPP){ //Need to treat this in a special way! Remove li, keep //li and have some sort of timeout? MULTI_DEBUG_PRINT_SYSLOG(stderr, "Could not get info for PPP " "link %u (first look)!\n", ifi->ifi_index); } else { //Clean the information that is automatically added to //routing table multi_link_remove_ppp(li); } } else if(wireless_mode){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Link %s is wlan access point\n", if_name); li->state = LINK_DOWN_AP; multi_link_get_iface_info(li); //Remove the automatic route multi_link_remove_ap(li); } else { pthread_attr_init(&detach_attr); pthread_attr_setdetachstate(&detach_attr, PTHREAD_CREATE_DETACHED); pthread_create(&(li->dhcp_thread), &detach_attr, multi_dhcp_main, (void *) li); } } else MULTI_DEBUG_PRINT_SYSLOG(stderr, "Limit reached, cannot add more links\n"); } else if(ifi->ifi_flags & IFF_UP){ //Might replace with IF_OPER_DOWN //Check if interface has already been seen LIST_FIND_CUSTOM(li, &multi_link_links_2, next, &(ifi->ifi_index), multi_cmp_ifidx); //Interface is already seen as UP, so clean up, no matter if static //or not. Static is a special case: remove routes, li from list //and free li if(li != NULL){ //Need a generic cleanup, move the next "else" into a separate //function MULTI_DEBUG_PRINT_SYSLOG(stderr,"Interface %s (idx %u) has already " "been seen as UP, will clean\n", if_name, ifi->ifi_index); multi_link_delete_link(li, probe_pipe); return; } //Check if interface is in static list TAILQ_FIND_CUSTOM(li_static, &multi_shared_static_links, list_ptr, if_name, multi_cmp_devname); if(li_static != NULL && li_static->proto == PROTO_STATIC){ //Allocate a new link MULTI_DEBUG_PRINT_SYSLOG(stderr, "Link %s is UP\n", if_name); li = multi_link_create_new_link(if_name, li_static->metric); if (li == NULL) { MULTI_DEBUG_PRINT_SYSLOG(stderr, "Failed to create new link\n"); return; } li->state = GOT_IP_STATIC_UP; li->cfg = li_static->cfg_static; LIST_INSERT_HEAD(&multi_link_links_2, li, next); ++multi_link_num_links; } } else { uint32_t dev_idx = ifi->ifi_index; LIST_FIND_CUSTOM(li, &multi_link_links_2, next, &dev_idx, multi_cmp_ifidx); MULTI_DEBUG_PRINT_SYSLOG(stderr, "Interface %s (index %u) is down, " "length %u\n", if_name, ifi->ifi_index, multi_link_num_links); if(li == NULL){ MULTI_DEBUG_PRINT_SYSLOG(stderr, "Could not find %s (index %u), " "length %u\n", if_name, ifi->ifi_index, multi_link_num_links); } else{ multi_link_delete_link(li, probe_pipe); } } } }
static int res_pd_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct nlattr *nla_table, *nla_entry; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_PD]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); nla_table = tb[RDMA_NLDEV_ATTR_RES_PD]; mnl_attr_for_each_nested(nla_entry, nla_table) { uint32_t local_dma_lkey = 0, unsafe_global_rkey = 0; struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; char *comm = NULL; uint32_t pid = 0; uint64_t users; int err; err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (err != MNL_CB_OK) return MNL_CB_ERROR; if (!nla_line[RDMA_NLDEV_ATTR_RES_USECNT] || (!nla_line[RDMA_NLDEV_ATTR_RES_PID] && !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) { return MNL_CB_ERROR; } if (nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]) local_dma_lkey = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]); users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]); if (rd_check_is_filtered(rd, "users", users)) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]) unsafe_global_rkey = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]); if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { pid = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_PID]); comm = get_task_name(pid); } if (rd_check_is_filtered(rd, "pid", pid)) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) /* discard const from mnl_attr_get_str */ comm = (char *)mnl_attr_get_str( nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]); if (rd->json_output) jsonw_start_array(rd->jw); print_dev(rd, idx, name); if (nla_line[RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY]) print_key(rd, "local_dma_lkey", local_dma_lkey); print_users(rd, users); if (nla_line[RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY]) print_key(rd, "unsafe_global_rkey", unsafe_global_rkey); print_pid(rd, pid); print_comm(rd, comm, nla_line); if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) free(comm); print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); newline(rd); }
static int res_mr_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct nlattr *nla_table, *nla_entry; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_MR]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); nla_table = tb[RDMA_NLDEV_ATTR_RES_MR]; mnl_attr_for_each_nested(nla_entry, nla_table) { struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; uint32_t rkey = 0, lkey = 0; uint64_t iova = 0, mrlen; char *comm = NULL; uint32_t pid = 0; int err; err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (err != MNL_CB_OK) return MNL_CB_ERROR; if (!nla_line[RDMA_NLDEV_ATTR_RES_MRLEN] || (!nla_line[RDMA_NLDEV_ATTR_RES_PID] && !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) { return MNL_CB_ERROR; } if (nla_line[RDMA_NLDEV_ATTR_RES_RKEY]) rkey = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_RKEY]); if (nla_line[RDMA_NLDEV_ATTR_RES_LKEY]) lkey = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_LKEY]); if (nla_line[RDMA_NLDEV_ATTR_RES_IOVA]) iova = mnl_attr_get_u64( nla_line[RDMA_NLDEV_ATTR_RES_IOVA]); mrlen = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_MRLEN]); if (rd_check_is_filtered(rd, "mrlen", mrlen)) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { pid = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_PID]); comm = get_task_name(pid); } if (rd_check_is_filtered(rd, "pid", pid)) { free(comm); continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) /* discard const from mnl_attr_get_str */ comm = (char *)mnl_attr_get_str( nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]); if (rd->json_output) jsonw_start_array(rd->jw); print_dev(rd, idx, name); if (nla_line[RDMA_NLDEV_ATTR_RES_RKEY]) print_key(rd, "rkey", rkey); if (nla_line[RDMA_NLDEV_ATTR_RES_LKEY]) print_key(rd, "lkey", lkey); if (nla_line[RDMA_NLDEV_ATTR_RES_IOVA]) print_iova(rd, iova); print_mrlen(rd, mrlen); print_pid(rd, pid); print_comm(rd, comm, nla_line); if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) free(comm); print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); newline(rd); } return MNL_CB_OK; }
static int res_cq_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct nlattr *nla_table, *nla_entry; struct rd *rd = data; const char *name; uint32_t idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_CQ]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); nla_table = tb[RDMA_NLDEV_ATTR_RES_CQ]; mnl_attr_for_each_nested(nla_entry, nla_table) { struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; char *comm = NULL; uint32_t pid = 0; uint8_t poll_ctx = 0; uint64_t users; uint32_t cqe; int err; err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (err != MNL_CB_OK) return MNL_CB_ERROR; if (!nla_line[RDMA_NLDEV_ATTR_RES_CQE] || !nla_line[RDMA_NLDEV_ATTR_RES_USECNT] || (!nla_line[RDMA_NLDEV_ATTR_RES_PID] && !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) { return MNL_CB_ERROR; } cqe = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_CQE]); users = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_USECNT]); if (rd_check_is_filtered(rd, "users", users)) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]) { poll_ctx = mnl_attr_get_u8( nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]); if (rd_check_is_string_filtered(rd, "poll-ctx", poll_ctx_to_str(poll_ctx))) continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { pid = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_PID]); comm = get_task_name(pid); } if (rd_check_is_filtered(rd, "pid", pid)) { free(comm); continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) /* discard const from mnl_attr_get_str */ comm = (char *)mnl_attr_get_str( nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]); if (rd->json_output) jsonw_start_array(rd->jw); print_dev(rd, idx, name); print_cqe(rd, cqe); print_users(rd, users); if (nla_line[RDMA_NLDEV_ATTR_RES_POLL_CTX]) print_poll_ctx(rd, poll_ctx); print_pid(rd, pid); print_comm(rd, comm, nla_line); if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) free(comm); print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); newline(rd); } return MNL_CB_OK; }
static int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {}; struct nlattr *nla_table, *nla_entry; struct rd *rd = data; const char *name; int idx; mnl_attr_parse(nlh, 0, rd_attr_cb, tb); if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_RES_CM_ID]) return MNL_CB_ERROR; name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]); idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]); nla_table = tb[RDMA_NLDEV_ATTR_RES_CM_ID]; mnl_attr_for_each_nested(nla_entry, nla_table) { struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {}; char src_addr_str[INET6_ADDRSTRLEN]; char dst_addr_str[INET6_ADDRSTRLEN]; uint16_t src_port, dst_port; uint32_t port = 0, pid = 0; uint8_t type = 0, state; uint32_t lqpn = 0, ps; char *comm = NULL; int err; err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line); if (err != MNL_CB_OK) return -EINVAL; if (!nla_line[RDMA_NLDEV_ATTR_RES_STATE] || !nla_line[RDMA_NLDEV_ATTR_RES_PS] || (!nla_line[RDMA_NLDEV_ATTR_RES_PID] && !nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME])) { return MNL_CB_ERROR; } if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]) port = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]); if (port && port != rd->port_idx) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN]) { lqpn = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_LQPN]); if (rd_check_is_filtered(rd, "lqpn", lqpn)) continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE]) { type = mnl_attr_get_u8( nla_line[RDMA_NLDEV_ATTR_RES_TYPE]); if (rd_check_is_string_filtered(rd, "qp-type", qp_types_to_str(type))) continue; } ps = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PS]); if (rd_check_is_string_filtered(rd, "ps", cm_id_ps_to_str(ps))) continue; state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]); if (rd_check_is_string_filtered(rd, "state", cm_id_state_to_str(state))) continue; if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]) { if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR], src_addr_str, &src_port)) continue; if (rd_check_is_string_filtered(rd, "src-addr", src_addr_str)) continue; if (rd_check_is_filtered(rd, "src-port", src_port)) continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]) { if (ss_ntop(nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR], dst_addr_str, &dst_port)) continue; if (rd_check_is_string_filtered(rd, "dst-addr", dst_addr_str)) continue; if (rd_check_is_filtered(rd, "dst-port", dst_port)) continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { pid = mnl_attr_get_u32( nla_line[RDMA_NLDEV_ATTR_RES_PID]); comm = get_task_name(pid); } if (rd_check_is_filtered(rd, "pid", pid)) { free(comm); continue; } if (nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]) { /* discard const from mnl_attr_get_str */ comm = (char *)mnl_attr_get_str( nla_line[RDMA_NLDEV_ATTR_RES_KERN_NAME]); } if (rd->json_output) jsonw_start_array(rd->jw); print_link(rd, idx, name, port, nla_line); if (nla_line[RDMA_NLDEV_ATTR_RES_LQPN]) print_lqpn(rd, lqpn); if (nla_line[RDMA_NLDEV_ATTR_RES_TYPE]) print_qp_type(rd, type); print_cm_id_state(rd, state); print_ps(rd, ps); print_pid(rd, pid); print_comm(rd, comm, nla_line); if (nla_line[RDMA_NLDEV_ATTR_RES_SRC_ADDR]) print_ipaddr(rd, "src-addr", src_addr_str, src_port); if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]) print_ipaddr(rd, "dst-addr", dst_addr_str, dst_port); if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) free(comm); print_driver_table(rd, nla_line[RDMA_NLDEV_ATTR_DRIVER]); newline(rd); } return MNL_CB_OK; }