Пример #1
0
static void put_msg(char *buf, uint16_t i, int seq)
{
	struct nlmsghdr *nlh;
	struct nfgenmsg *nfh;
	struct nlattr *nest1, *nest2;

	nlh = mnl_nlmsg_put_header(buf);
	nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
	nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
	nlh->nlmsg_seq = seq;

	nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
	nfh->nfgen_family = AF_INET;
	nfh->version = NFNETLINK_V0;
	nfh->res_id = 0;

	nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_ORIG);
	nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
	mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("1.1.1.1"));
	mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("2.2.2.2"));
	mnl_attr_nest_end(nlh, nest2);

	nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
	mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP);
	mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(i));
	mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(1025));
	mnl_attr_nest_end(nlh, nest2);
	mnl_attr_nest_end(nlh, nest1);

	nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_REPLY);
	nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
	mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("2.2.2.2"));
	mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("1.1.1.1"));
	mnl_attr_nest_end(nlh, nest2);

	nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
	mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP);
	mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(1025));
	mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(i));
	mnl_attr_nest_end(nlh, nest2);
	mnl_attr_nest_end(nlh, nest1);

	nest1 = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
	nest2 = mnl_attr_nest_start(nlh, CTA_PROTOINFO_TCP);
	mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_STATE, TCP_CONNTRACK_SYN_SENT);
	mnl_attr_nest_end(nlh, nest2);
	mnl_attr_nest_end(nlh, nest1);

	mnl_attr_put_u32(nlh, CTA_STATUS, htonl(IPS_CONFIRMED));
	mnl_attr_put_u32(nlh, CTA_TIMEOUT, htonl(1000));
}
Пример #2
0
static int
nfct_build_tuple_proto(struct nlmsghdr *nlh, const struct __nfct_tuple *t)
{
	struct nlattr *nest;

	nest = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
	if (nest == NULL)
		return -1;

	mnl_attr_put_u8(nlh, CTA_PROTO_NUM, t->protonum);

	switch(t->protonum) {
	case IPPROTO_UDP:
	case IPPROTO_TCP:
	case IPPROTO_SCTP:
	case IPPROTO_DCCP:
	case IPPROTO_GRE:
	case IPPROTO_UDPLITE:
		mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, t->l4src.tcp.port);
		mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, t->l4dst.tcp.port);
		break;
	case IPPROTO_ICMP:
		mnl_attr_put_u8(nlh, CTA_PROTO_ICMP_CODE, t->l4dst.icmp.code);
		mnl_attr_put_u8(nlh, CTA_PROTO_ICMP_TYPE, t->l4dst.icmp.type);
		mnl_attr_put_u16(nlh, CTA_PROTO_ICMP_ID, t->l4src.icmp.id);
		break;
	case IPPROTO_ICMPV6:
		mnl_attr_put_u8(nlh, CTA_PROTO_ICMPV6_CODE, t->l4dst.icmp.code);
		mnl_attr_put_u8(nlh, CTA_PROTO_ICMPV6_TYPE, t->l4dst.icmp.type);
		mnl_attr_put_u16(nlh, CTA_PROTO_ICMPV6_ID, t->l4src.icmp.id);
		break;
	default:
		mnl_attr_nest_cancel(nlh, nest);
		return -1;
	}
	mnl_attr_nest_end(nlh, nest);
	return 0;
}
Пример #3
0
static void
nft_rule_expr_ct_build(struct nlmsghdr *nlh, struct nft_rule_expr *e)
{
	struct nft_expr_ct *ct = nft_expr_data(e);

	if (e->flags & (1 << NFT_EXPR_CT_KEY))
		mnl_attr_put_u32(nlh, NFTA_CT_KEY, htonl(ct->key));
	if (e->flags & (1 << NFT_EXPR_CT_DREG))
		mnl_attr_put_u32(nlh, NFTA_CT_DREG, htonl(ct->dreg));
	if (e->flags & (1 << NFT_EXPR_CT_DIR))
		mnl_attr_put_u8(nlh, NFTA_CT_DIRECTION, ct->dir);
	if (e->flags & (1 << NFT_EXPR_CT_SREG))
		mnl_attr_put_u32(nlh, NFTA_CT_SREG, htonl(ct->sreg));
}
Пример #4
0
static int
nfct_build_protoinfo(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
{
	struct nlattr *nest, *nest_proto;

	switch(ct->head.orig.protonum) {
	case IPPROTO_TCP:
		/* Preliminary attribute check to avoid sending an empty
		 * CTA_PROTOINFO_TCP nest, which results in EINVAL in
		 * Linux kernel <= 2.6.25. */
		if (!(test_bit(ATTR_TCP_STATE, ct->head.set) ||
		      test_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set) ||
		      test_bit(ATTR_TCP_FLAGS_REPL, ct->head.set) ||
		      test_bit(ATTR_TCP_MASK_ORIG, ct->head.set) ||
		      test_bit(ATTR_TCP_MASK_REPL, ct->head.set) ||
		      test_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set) ||
		      test_bit(ATTR_TCP_WSCALE_REPL, ct->head.set))) {
			break;
		}
		nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
		nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_TCP);
		if (test_bit(ATTR_TCP_STATE, ct->head.set)) {
			mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_STATE,
					ct->protoinfo.tcp.state);
		}
		if (test_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set) &&
		    test_bit(ATTR_TCP_MASK_ORIG, ct->head.set)) {
			mnl_attr_put(nlh, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
				     sizeof(struct nf_ct_tcp_flags),
				     &ct->protoinfo.tcp.flags[0]);
		}
		if (test_bit(ATTR_TCP_FLAGS_REPL, ct->head.set) &&
		    test_bit(ATTR_TCP_MASK_REPL, ct->head.set)) {
			mnl_attr_put(nlh, CTA_PROTOINFO_TCP_FLAGS_REPLY,
				     sizeof(struct nf_ct_tcp_flags),
				     &ct->protoinfo.tcp.flags[1]);
		}
		if (test_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set)) {
			mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
					ct->protoinfo.tcp.wscale[__DIR_ORIG]);
		}
		if (test_bit(ATTR_TCP_WSCALE_REPL, ct->head.set)) {
			mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_WSCALE_REPLY,
					ct->protoinfo.tcp.wscale[__DIR_REPL]);
		}
		mnl_attr_nest_end(nlh, nest_proto);
		mnl_attr_nest_end(nlh, nest);
		break;
	case IPPROTO_SCTP:
		/* See comment above on TCP. */
		if (!(test_bit(ATTR_SCTP_STATE, ct->head.set) ||
		      test_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set) ||
		      test_bit(ATTR_SCTP_VTAG_REPL, ct->head.set))) {
			break;
		}
		nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
		nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_SCTP);

		if (test_bit(ATTR_SCTP_STATE, ct->head.set)) {
			mnl_attr_put_u8(nlh, CTA_PROTOINFO_SCTP_STATE,
					ct->protoinfo.sctp.state);
		}
		if (test_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set)) {
			mnl_attr_put_u32(nlh, CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
				htonl(ct->protoinfo.sctp.vtag[__DIR_ORIG]));
		}
		if (test_bit(ATTR_SCTP_VTAG_REPL, ct->head.set)) {
			mnl_attr_put_u32(nlh, CTA_PROTOINFO_SCTP_VTAG_REPLY,
				htonl(ct->protoinfo.sctp.vtag[__DIR_REPL]));
		}
		mnl_attr_nest_end(nlh, nest_proto);
		mnl_attr_nest_end(nlh, nest);
		break;
	case IPPROTO_DCCP:
		/* See comment above on TCP. */
		if (!(test_bit(ATTR_DCCP_STATE, ct->head.set) ||
		      test_bit(ATTR_DCCP_ROLE, ct->head.set) ||
		      test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set))) {
			break;
		}
		nest = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
		nest_proto = mnl_attr_nest_start(nlh, CTA_PROTOINFO_DCCP);
		if (test_bit(ATTR_DCCP_STATE, ct->head.set)) {
			mnl_attr_put_u8(nlh, CTA_PROTOINFO_DCCP_STATE,
					ct->protoinfo.dccp.state);
		}
		if (test_bit(ATTR_DCCP_ROLE, ct->head.set)) {
			mnl_attr_put_u8(nlh, CTA_PROTOINFO_DCCP_ROLE,
					ct->protoinfo.dccp.role);
		}
		if (test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set)) {
			uint64_t handshake_seq =
				be64toh(ct->protoinfo.dccp.handshake_seq);

			mnl_attr_put_u64(nlh, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
					 handshake_seq);
		}
		mnl_attr_nest_end(nlh, nest_proto);
		mnl_attr_nest_end(nlh, nest);
	default:
		break;
	}
	return 0;
}