Пример #1
0
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]));
	}
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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);
            }
        }
    }
}
Пример #7
0
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;
}
Пример #8
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
/* 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;
}