Example #1
0
static void print_ip(const struct nlattr *nest)
{
	struct nlattr *tb[CTA_IP_MAX+1] = {};

	mnl_attr_parse_nested(nest, parse_ip_cb, tb);
	if (tb[CTA_IP_V4_SRC]) {
		struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]);
		printf("src=%s ", inet_ntoa(*in));
	}
	if (tb[CTA_IP_V4_DST]) {
		struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]);
		printf("dst=%s ", inet_ntoa(*in));
	}
	if (tb[CTA_IP_V6_SRC]) {
		struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_SRC]);
		char out[INET6_ADDRSTRLEN];

		if (!inet_ntop(AF_INET6, in, out, sizeof(out)))
			printf("src=%s ", out);
	}
	if (tb[CTA_IP_V6_DST]) {
		struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_DST]);
		char out[INET6_ADDRSTRLEN];

		if (!inet_ntop(AF_INET6, in, out, sizeof(out)))
			printf("dst=%s ", out);
	}
}
Example #2
0
//Function which parses the netlink message (*ADDR) we have received and extract
//relevant information, which is parsed to OS-independent
//neat_addr_update_src_list
static void neat_linux_handle_addr(struct neat_ctx *nc,
                                   struct nlmsghdr *nl_hdr)
{
    struct ifaddrmsg *ifm = (struct ifaddrmsg*) mnl_nlmsg_get_payload(nl_hdr);
    const struct nlattr *attr_table[IFA_MAX+1];
    //IFA_MAX is the largest index I can store in my array. Since arrays are
    //zero-indexed, this is IFA_MAX and not IFA_MAX + 1. However, array has to
    //be of size IFA_MAX + 1. DOH!
    struct nlattr_storage tb_storage = {attr_table, IFA_MAX};
    struct sockaddr_storage src_addr;
    struct sockaddr_in *src_addr4;
    struct sockaddr_in6 *src_addr6;
    struct ifa_cacheinfo *ci;
    uint32_t *addr6_ptr, ifa_pref = 0, ifa_valid = 0;
    uint8_t i;

    //On Linux, lo has a fixed index. We have no interest in that interface
    //TODO: Consider other filters - bridges, ifb, ...
    if (ifm->ifa_index == LO_DEV_IDX)
        return;

    if (ifm->ifa_scope == RT_SCOPE_LINK)
        return;

    memset(attr_table, 0, sizeof(attr_table));
    memset(&src_addr, 0, sizeof(src_addr));

    if (mnl_attr_parse(nl_hdr, sizeof(struct ifaddrmsg),
                neat_linux_parse_nlattr, &tb_storage) != MNL_CB_OK) {
        fprintf(stderr, "Failed to parse nlattr for msg of type %d\n",
                nl_hdr->nlmsg_type);
        return;
    }

    //v4 and v6 has to be handled differently, both due to address size and
    //available information
    if (ifm->ifa_family == AF_INET) {
        src_addr4 = (struct sockaddr_in*) &src_addr;
        src_addr4->sin_family = AF_INET;
        src_addr4->sin_addr.s_addr = mnl_attr_get_u32(attr_table[IFA_LOCAL]);
    } else {
        src_addr6 = (struct sockaddr_in6*) &src_addr;
        src_addr6->sin6_family = AF_INET6;
        addr6_ptr = (uint32_t*) mnl_attr_get_payload(attr_table[IFA_ADDRESS]);

        for (i=0; i<4; i++)
            src_addr6->sin6_addr.s6_addr32[i] = *(addr6_ptr + i);

        ci = (struct ifa_cacheinfo*) mnl_attr_get_payload(attr_table[IFA_CACHEINFO]);
        ifa_pref = ci->ifa_prefered;
        ifa_valid = ci->ifa_valid;
    }

    //TODO: Should this function be a callback instead? Will we have multiple
    //addresses handlers/types of context?
    neat_addr_update_src_list(nc, &src_addr, ifm->ifa_index,
            nl_hdr->nlmsg_type == RTM_NEWADDR, ifa_pref, ifa_valid);
}
Example #3
0
//Function which parses the netlink message (*ADDR) we have received and extract
//relevant information, which is parsed to OS-independent
//neat_addr_update_src_list
static neat_error_code
nt_linux_handle_addr(struct neat_ctx *ctx, struct nlmsghdr *nl_hdr)
{
    struct ifaddrmsg *ifm = (struct ifaddrmsg*) mnl_nlmsg_get_payload(nl_hdr);
    const struct nlattr *attr_table[IFA_MAX+1];
    //IFA_MAX is the largest index I can store in my array. Since arrays are
    //zero-indexed, this is IFA_MAX and not IFA_MAX + 1. However, array has to
    //be of size IFA_MAX + 1. DOH!
    struct nlattr_storage tb_storage = {attr_table, IFA_MAX};
    struct sockaddr_storage src_addr;
    struct sockaddr_in *src_addr4;
    struct sockaddr_in6 *src_addr6;
    struct ifa_cacheinfo *ci;
    uint32_t ifa_pref = 0, ifa_valid = 0;

    if (ifm->ifa_scope == RT_SCOPE_LINK)
        return NEAT_ERROR_OK;

    memset(attr_table, 0, sizeof(attr_table));
    memset(&src_addr, 0, sizeof(src_addr));

    if (mnl_attr_parse(nl_hdr, sizeof(struct ifaddrmsg),
                neat_linux_parse_nlattr, &tb_storage) != MNL_CB_OK) {
        nt_log(ctx, NEAT_LOG_ERROR, "Failed to parse nlattr for msg of type %d",
                __func__, nl_hdr->nlmsg_type);
        return NEAT_ERROR_OK;
    }

    //v4 and v6 has to be handled differently, both due to address size and
    //available information
    if (ifm->ifa_family == AF_INET) {
        src_addr4 = (struct sockaddr_in*) &src_addr;
        src_addr4->sin_family = AF_INET;
        src_addr4->sin_addr.s_addr = mnl_attr_get_u32(attr_table[IFA_LOCAL]);
    } else {
        src_addr6 = (struct sockaddr_in6*) &src_addr;
        src_addr6->sin6_family = AF_INET6;
        memcpy(&src_addr6->sin6_addr, mnl_attr_get_payload(attr_table[IFA_ADDRESS]), sizeof(struct in6_addr));

        ci = (struct ifa_cacheinfo*) mnl_attr_get_payload(attr_table[IFA_CACHEINFO]);
        ifa_pref = ci->ifa_prefered;
        ifa_valid = ci->ifa_valid;
    }

    //TODO: Should this function be a callback instead? Will we have multiple
    //addresses handlers/types of context?
    return nt_addr_update_src_list(ctx, (struct sockaddr*) &src_addr, ifm->ifa_index,
                                     nl_hdr->nlmsg_type == RTM_NEWADDR,
                                     ifm->ifa_prefixlen, ifa_pref, ifa_valid);
}
Example #4
0
static int ss_ntop(struct nlattr *nla_line, char *addr_str, uint16_t *port)
{
	struct __kernel_sockaddr_storage *addr;

	addr = (struct __kernel_sockaddr_storage *)
						mnl_attr_get_payload(nla_line);
	switch (addr->ss_family) {
	case AF_INET: {
		struct sockaddr_in *sin = (struct sockaddr_in *)addr;

		if (!inet_ntop(AF_INET, (const void *)&sin->sin_addr, addr_str,
			       INET6_ADDRSTRLEN))
			return -EINVAL;
		*port = ntohs(sin->sin_port);
		break;
	}
	case AF_INET6: {
		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;

		if (!inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
			       addr_str, INET6_ADDRSTRLEN))
			return -EINVAL;
		*port = ntohs(sin6->sin6_port);
		break;
	}
	default:
		return -EINVAL;
	}
	return 0;
}
Example #5
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;
}
Example #6
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;
}
Example #7
0
static void attributes_show_ipv4(struct nlattr *tb[])
{
	if (tb[RTA_TABLE]) {
		printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
	}
	if (tb[RTA_DST]) {
		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
		printf("dst=%s ", inet_ntoa(*addr));
	}
	if (tb[RTA_SRC]) {
		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
		printf("src=%s ", inet_ntoa(*addr));
	}
	if (tb[RTA_OIF]) {
		printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
	}
	if (tb[RTA_FLOW]) {
		printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
	}
	if (tb[RTA_PREFSRC]) {
		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
		printf("prefsrc=%s ", inet_ntoa(*addr));
	}
	if (tb[RTA_GATEWAY]) {
		struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
		printf("gw=%s ", inet_ntoa(*addr));
	}
	if (tb[RTA_PRIORITY]) {
		printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
	}
	if (tb[RTA_METRICS]) {
		int i;
		struct nlattr *tbx[RTAX_MAX+1] = {};

		mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);

		for (i=0; i<RTAX_MAX; i++) {
			if (tbx[i]) {
				printf("metrics[%d]=%u ",
					i, mnl_attr_get_u32(tbx[i]));
			}
		}
	}
	printf("\n");
}
Example #8
0
static int link_mon_peer_list_cb(const struct nlmsghdr *nlh, void *data)
{
	struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
	struct nlattr *attrs[TIPC_NLA_MON_PEER_MAX + 1] = {};
	struct nlattr *info[TIPC_NLA_MAX + 1] = {};
	uint16_t member_cnt;
	uint32_t applied;
	uint32_t dom_gen;
	uint64_t up_map;
	char status[16];
	char monitored[16];

	mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info);
	if (!info[TIPC_NLA_MON_PEER])
		return MNL_CB_ERROR;

	open_json_object(NULL);
	mnl_attr_parse_nested(info[TIPC_NLA_MON_PEER], parse_attrs, attrs);

	(attrs[TIPC_NLA_MON_PEER_LOCAL] || attrs[TIPC_NLA_MON_PEER_HEAD]) ?
		strcpy(monitored, "direct") :
		strcpy(monitored, "indirect");

	attrs[TIPC_NLA_MON_PEER_UP] ?
		strcpy(status, "up") :
		strcpy(status, "down");

	dom_gen = attrs[TIPC_NLA_MON_PEER_DOMGEN] ?
		mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_DOMGEN]) : 0;

	link_mon_print_peer_state(mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_ADDR]),
				  status, monitored, dom_gen);

	applied = mnl_attr_get_u32(attrs[TIPC_NLA_MON_PEER_APPLIED]);

	if (!applied)
		goto exit;

	up_map = mnl_attr_get_u64(attrs[TIPC_NLA_MON_PEER_UPMAP]);

	member_cnt = mnl_attr_get_payload_len(attrs[TIPC_NLA_MON_PEER_MEMBERS]);

	/* each tipc address occupies 4 bytes of payload, hence compensate it */
	member_cnt /= sizeof(uint32_t);

	link_mon_print_applied(applied, up_map);

	link_mon_print_non_applied(applied, member_cnt, up_map,
				   mnl_attr_get_payload(attrs[TIPC_NLA_MON_PEER_MEMBERS]));

exit:
	print_string(PRINT_FP, NULL, "\n", "");

	close_json_object();
	return MNL_CB_OK;
}
Example #9
0
/**
 * mnl_attr_put - add an attribute to netlink message
 * \param nlh pointer to the netlink message
 * \param type netlink attribute type that you want to add
 * \param len netlink attribute payload length
 * \param data pointer to the data that will be stored by the new attribute
 *
 * This function updates the length field of the Netlink message (nlmsg_len)
 * by adding the size (header + payload) of the new attribute.
 */
void
mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
{
	struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
	uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;

	attr->nla_type = type;
	attr->nla_len = payload_len;
	memcpy(mnl_attr_get_payload(attr), data, len);
	nlh->nlmsg_len += MNL_ALIGN(payload_len);
}
Example #10
0
static int __mnl_attr_validate(const struct nlattr *attr,
			       enum mnl_attr_data_type type, size_t exp_len)
{
	uint16_t attr_len = mnl_attr_get_payload_len(attr);
	const char *attr_data = mnl_attr_get_payload(attr);

	if (attr_len < exp_len) {
		errno = ERANGE;
		return -1;
	}
	switch(type) {
	case MNL_TYPE_FLAG:
		if (attr_len > 0) {
			errno = ERANGE;
			return -1;
		}
		break;
	case MNL_TYPE_NUL_STRING:
		if (attr_len == 0) {
			errno = ERANGE;
			return -1;
		}
		if (attr_data[attr_len-1] != '\0') {
			errno = EINVAL;
			return -1;
		}
		break;
	case MNL_TYPE_STRING:
		if (attr_len == 0) {
			errno = ERANGE;
			return -1;
		}
		break;
	case MNL_TYPE_NESTED:
		/* empty nested attributes are OK. */
		if (attr_len == 0)
			break;
		/* if not empty, they must contain one header, eg. flag */
		if (attr_len < MNL_ATTR_HDRLEN) {
			errno = ERANGE;
			return -1;
		}
		break;
	default:
		/* make gcc happy. */
		break;
	}
	if (exp_len && attr_len > exp_len) {
		errno = ERANGE;
		return -1;
	}
	return 0;
}
Example #11
0
static int queue_cb(const struct nlmsghdr *nlh, void *data)
{
	struct nlattr *tb[NFQA_MAX+1] = {};
	struct nfqnl_msg_packet_hdr *ph = NULL;
	uint32_t id = 0;

	mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
	if (tb[NFQA_PACKET_HDR]) {
		ph = mnl_attr_get_payload(tb[NFQA_PACKET_HDR]);
		id = ntohl(ph->packet_id);
	}
	printf("packet received (id=%u hw=0x%04x hook=%u)\n",
		id, ntohs(ph->hw_protocol), ph->hook);

	return MNL_CB_OK + id;
}
Example #12
0
static int nfct_parse_labels(const struct nlattr *attr, struct nf_conntrack *ct)
{
	uint16_t len = mnl_attr_get_payload_len(attr);
	struct nfct_bitmask *mask;
	uint32_t *bits;

	if (len == 0)
		return 0;

	mask = nfct_bitmask_new((len * CHAR_BIT) - 1);
	if (!mask)
		return -1;
	bits = mnl_attr_get_payload(attr);

	memcpy(mask->bits, bits, len);
	nfct_set_attr(ct, ATTR_CONNLABELS, mask);
	return 0;
}
Example #13
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;
}
Example #14
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;
}
Example #15
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;
}
Example #16
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;
}
Example #17
0
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;
}
Example #18
0
/**
 * mnl_attr_get_u8 - returns 8-bit unsigned integer attribute payload
 * \param attr pointer to netlink attribute
 *
 * This function returns the 8-bit value of the attribute payload.
 */
EXPORT_SYMBOL uint8_t mnl_attr_get_u8(const struct nlattr *attr)
{
	return *((uint8_t *)mnl_attr_get_payload(attr));
}
Example #19
0
/**
 * mnl_attr_get_str - returns pointer to string attribute.
 * \param attr pointer to netlink attribute
 *
 * This function returns the payload of string attribute value.
 */
const char *mnl_attr_get_str(const struct nlattr *attr)
{
	return mnl_attr_get_payload(attr);
}
Example #20
0
/**
 * mnl_attr_get_u64 - returns 64-bit unsigned integer attribute.
 * \param attr pointer to netlink attribute
 *
 * This function returns the 64-bit value of the attribute payload. This
 * function is align-safe, since accessing 64-bit Netlink attributes is a
 * common source of alignment issues.
 */
uint64_t mnl_attr_get_u64(const struct nlattr *attr)
{
	uint64_t tmp;
	memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
	return tmp;
}
Example #21
0
/**
 * mnl_attr_get_u32 - returns 32-bit unsigned integer attribute payload
 * \param attr pointer to netlink attribute
 *
 * This function returns the 32-bit value of the attribute payload.
 */
uint32_t mnl_attr_get_u32(const struct nlattr *attr)
{
	return *((uint32_t *)mnl_attr_get_payload(attr));
}
Example #22
0
/**
 * mnl_attr_get_u16 - returns 16-bit unsigned integer attribute payload
 * \param attr pointer to netlink attribute
 *
 * This function returns the 16-bit value of the attribute payload.
 */
uint16_t mnl_attr_get_u16(const struct nlattr *attr)
{
	return *((uint16_t *)mnl_attr_get_payload(attr));
}
Example #23
0
static int
nfct_parse_ip(const struct nlattr *attr, struct __nfct_tuple *tuple,
	     const int dir, u_int32_t *set)
{
	struct nlattr *tb[CTA_IP_MAX+1] = {};

	if (mnl_attr_parse_nested(attr, nfct_parse_ip_attr_cb, tb) < 0)
		return -1;

	if (tb[CTA_IP_V4_SRC]) {
		tuple->src.v4 = mnl_attr_get_u32(tb[CTA_IP_V4_SRC]);
		switch(dir) {
		case __DIR_ORIG:
			set_bit(ATTR_ORIG_IPV4_SRC, set);
			break;
		case __DIR_REPL:
			set_bit(ATTR_REPL_IPV4_SRC, set);
			break;
		case __DIR_MASTER:
			set_bit(ATTR_MASTER_IPV4_SRC, set);
			break;
		}
	}

	if (tb[CTA_IP_V4_DST]) {
		tuple->dst.v4 = mnl_attr_get_u32(tb[CTA_IP_V4_DST]);
		switch(dir) {
		case __DIR_ORIG:
			set_bit(ATTR_ORIG_IPV4_DST, set);
			break;
		case __DIR_REPL:
			set_bit(ATTR_REPL_IPV4_DST, set);
			break;
		case __DIR_MASTER:
			set_bit(ATTR_MASTER_IPV4_DST, set);
			break;
		}
	}

	if (tb[CTA_IP_V6_SRC]) {
		memcpy(&tuple->src.v6, mnl_attr_get_payload(tb[CTA_IP_V6_SRC]),
		       sizeof(struct in6_addr));
		switch(dir) {
		case __DIR_ORIG:
			set_bit(ATTR_ORIG_IPV6_SRC, set);
			break;
		case __DIR_REPL:
			set_bit(ATTR_REPL_IPV6_SRC, set);
			break;
		case __DIR_MASTER:
			set_bit(ATTR_MASTER_IPV6_SRC, set);
			break;
		}
	}

	if (tb[CTA_IP_V6_DST]) {
		memcpy(&tuple->dst.v6, mnl_attr_get_payload(tb[CTA_IP_V6_DST]),
		       sizeof(struct in6_addr));
		switch(dir) {
		case __DIR_ORIG:
			set_bit(ATTR_ORIG_IPV6_DST, set);
			break;
		case __DIR_REPL:
			set_bit(ATTR_REPL_IPV6_DST, set);
			break;
		case __DIR_MASTER:
			set_bit(ATTR_MASTER_IPV6_DST, set);
			break;
		}
	}
	return 0;
}