static void print_proto(const struct nlattr *nest) { struct nlattr *tb[CTA_PROTO_MAX+1] = {}; mnl_attr_parse_nested(nest, parse_proto_cb, tb); if (tb[CTA_PROTO_NUM]) { printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM])); } if (tb[CTA_PROTO_SRC_PORT]) { printf("sport=%u ", ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT]))); } if (tb[CTA_PROTO_DST_PORT]) { printf("dport=%u ", ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT]))); } if (tb[CTA_PROTO_ICMP_ID]) { printf("id=%u ", ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID]))); } if (tb[CTA_PROTO_ICMP_TYPE]) { printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE])); } if (tb[CTA_PROTO_ICMP_CODE]) { printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE])); } }
static int nfct_parse_protoinfo_sctp(const struct nlattr *attr, struct nf_conntrack *ct) { struct nlattr *tb[CTA_PROTOINFO_SCTP_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_sctp_attr_cb, tb) < 0) return -1; if (tb[CTA_PROTOINFO_SCTP_STATE]) { ct->protoinfo.sctp.state = mnl_attr_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]); set_bit(ATTR_SCTP_STATE, ct->head.set); } if (tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]) { ct->protoinfo.sctp.vtag[__DIR_ORIG] = ntohl(mnl_attr_get_u32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL])); set_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set); } if (tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]) { ct->protoinfo.sctp.vtag[__DIR_REPL] = ntohl(mnl_attr_get_u32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])); set_bit(ATTR_SCTP_VTAG_REPL, ct->head.set); } return 0; }
static int nft_rule_expr_ct_parse(struct nft_rule_expr *e, struct nlattr *attr) { struct nft_expr_ct *ct = nft_expr_data(e); struct nlattr *tb[NFTA_CT_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nft_rule_expr_ct_cb, tb) < 0) return -1; if (tb[NFTA_CT_KEY]) { ct->key = ntohl(mnl_attr_get_u32(tb[NFTA_CT_KEY])); e->flags |= (1 << NFT_EXPR_CT_KEY); } if (tb[NFTA_CT_DREG]) { ct->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_CT_DREG])); e->flags |= (1 << NFT_EXPR_CT_DREG); } if (tb[NFTA_CT_SREG]) { ct->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_CT_SREG])); e->flags |= (1 << NFT_EXPR_CT_SREG); } if (tb[NFTA_CT_DIRECTION]) { ct->dir = mnl_attr_get_u8(tb[NFTA_CT_DIRECTION]); e->flags |= (1 << NFT_EXPR_CT_DIR); } return 0; }
static int nfct_parse_protoinfo_dccp(const struct nlattr *attr, struct nf_conntrack *ct) { struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_dccp_attr_cb, tb) < 0) return -1; if (tb[CTA_PROTOINFO_DCCP_STATE]) { ct->protoinfo.dccp.state = mnl_attr_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); set_bit(ATTR_DCCP_STATE, ct->head.set); } if (tb[CTA_PROTOINFO_DCCP_ROLE]) { ct->protoinfo.dccp.role = mnl_attr_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]); set_bit(ATTR_DCCP_ROLE, ct->head.set); } if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) { ct->protoinfo.dccp.handshake_seq = be64toh( mnl_attr_get_u64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ])); set_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set); } return 0; }
static int nfct_parse_protoinfo_tcp(const struct nlattr *attr, struct nf_conntrack *ct) { struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_pinfo_tcp_attr_cb, tb) < 0) return -1; if (tb[CTA_PROTOINFO_TCP_STATE]) { ct->protoinfo.tcp.state = mnl_attr_get_u8(tb[CTA_PROTOINFO_TCP_STATE]); set_bit(ATTR_TCP_STATE, ct->head.set); } if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]) { memcpy(&ct->protoinfo.tcp.wscale[__DIR_ORIG], mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]), sizeof(uint8_t)); set_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set); } if (tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]) { memcpy(&ct->protoinfo.tcp.wscale[__DIR_REPL], mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY]), sizeof(uint8_t)); set_bit(ATTR_TCP_WSCALE_REPL, ct->head.set); } if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]) { memcpy(&ct->protoinfo.tcp.flags[0], mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]), sizeof(struct nf_ct_tcp_flags)); set_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set); set_bit(ATTR_TCP_MASK_ORIG, ct->head.set); } if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]) { memcpy(&ct->protoinfo.tcp.flags[1], mnl_attr_get_payload(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY]), sizeof(struct nf_ct_tcp_flags)); set_bit(ATTR_TCP_FLAGS_REPL, ct->head.set); set_bit(ATTR_TCP_MASK_REPL, ct->head.set); } return 0; }
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 nfct_parse_proto(const struct nlattr *attr, struct __nfct_tuple *tuple, const int dir, u_int32_t *set) { struct nlattr *tb[CTA_PROTO_MAX+1] = {}; if (mnl_attr_parse_nested(attr, nfct_parse_proto_attr_cb, tb) < 0) return -1; if (tb[CTA_PROTO_NUM]) { tuple->protonum = mnl_attr_get_u8(tb[CTA_PROTO_NUM]); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_L4PROTO, set); break; case __DIR_REPL: set_bit(ATTR_REPL_L4PROTO, set); break; case __DIR_MASTER: set_bit(ATTR_MASTER_L4PROTO, set); break; } } if (tb[CTA_PROTO_SRC_PORT]) { tuple->l4src.tcp.port = mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT]); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_PORT_SRC, set); break; case __DIR_REPL: set_bit(ATTR_REPL_PORT_SRC, set); break; case __DIR_MASTER: set_bit(ATTR_MASTER_PORT_SRC, set); break; } } if (tb[CTA_PROTO_DST_PORT]) { tuple->l4dst.tcp.port = mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT]); switch(dir) { case __DIR_ORIG: set_bit(ATTR_ORIG_PORT_DST, set); break; case __DIR_REPL: set_bit(ATTR_REPL_PORT_DST, set); break; case __DIR_MASTER: set_bit(ATTR_MASTER_PORT_DST, set); break; } } if (tb[CTA_PROTO_ICMP_TYPE]) { tuple->l4dst.icmp.type = mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]); set_bit(ATTR_ICMP_TYPE, set); } if (tb[CTA_PROTO_ICMP_CODE]) { tuple->l4dst.icmp.code = mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]); set_bit(ATTR_ICMP_CODE, set); } if (tb[CTA_PROTO_ICMP_ID]) { tuple->l4src.icmp.id = mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID]); set_bit(ATTR_ICMP_ID, set); } if (tb[CTA_PROTO_ICMPV6_TYPE]) { tuple->l4dst.icmp.type = mnl_attr_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]); set_bit(ATTR_ICMP_TYPE, set); } if (tb[CTA_PROTO_ICMPV6_CODE]) { tuple->l4dst.icmp.code = mnl_attr_get_u8(tb[CTA_PROTO_ICMPV6_CODE]); set_bit(ATTR_ICMP_CODE, set); } if (tb[CTA_PROTO_ICMPV6_ID]) { tuple->l4src.icmp.id = mnl_attr_get_u16(tb[CTA_PROTO_ICMPV6_ID]); set_bit(ATTR_ICMP_ID, set); } return 0; }
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; }
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; }
/* returns negative on error * or returns remainded nlmsghdr length */ static int _unpack_nlmsg(const struct nlmsghdr *nlh, const char *format, va_list ap) { struct nlattr *attr = mnl_nlmsg_get_payload(nlh); int remains = (int)mnl_nlmsg_get_payload_len(nlh); size_t len; uint16_t atype, alen; void *p; while (*format != '\0' ) { if (!mnl_attr_ok(attr, remains)) { errno = EOVERFLOW; return -1; } remains -= MY_NLATTR_HDRLEN; atype = mnl_attr_get_type(attr); alen = mnl_attr_get_payload_len(attr); switch (*format) { case 'B': /* byte */ if (atype != MNL_TYPE_U8 || alen != sizeof(uint8_t)) { errno =EINVAL; return -1; } *(va_arg(ap, uint8_t *)) = mnl_attr_get_u8(attr); break; case 'H': /* 2byte */ if (atype != MNL_TYPE_U16 || alen != sizeof(uint16_t)) { errno = EINVAL; return -1; } *(va_arg(ap, uint16_t *)) = mnl_attr_get_u16(attr); break; case 'I': /* 4byte */ if (atype != MNL_TYPE_U32 || alen != sizeof(uint32_t)) { errno = EINVAL; return -1; } *(va_arg(ap, uint32_t *)) = mnl_attr_get_u32(attr); break; case 'K': /* 8byte */ if (atype != MNL_TYPE_U64 || alen != sizeof(uint64_t)) { errno = EINVAL; return -1; } *(va_arg(ap, uint64_t *)) = mnl_attr_get_u64(attr); break; case 'p': /* pointer */ if (atype != MNL_TYPE_BINARY || alen != sizeof(void *)) { errno = EINVAL; return -1; } *(va_arg(ap, void **)) = *((void **)mnl_attr_get_payload(attr)); break; case 'z': /* null string */ if (atype != MNL_TYPE_NUL_STRING) { errno = EINVAL; return -1; } p = va_arg(ap, void *); if (*(format + 1) == '#') { format++; len = va_arg(ap, size_t); if (alen > len) { errno = EINVAL; return -1; } } strncpy(p, mnl_attr_get_payload(attr), alen); break; case 'y': /* bytes with size */ format++; if (*format != '#') { errno = EINVAL; return -1; } p = va_arg(ap, void *); len = va_arg(ap, size_t); if (alen > len) return -EINVAL; memcpy(p, mnl_attr_get_payload(attr), alen); break; default: errno =EINVAL; return -1; } remains -= MY_ATTR_ALIGN(alen); format++; attr = mnl_attr_next(attr); } if (remains) { errno = EMSGSIZE; nurs_log(NURS_NOTICE, "unpack remains: %d\n", remains); } return remains; }