Esempio n. 1
0
void __build_tuple_ip(struct nfnlhdr *req, 
		      size_t size,
		      const struct __nfct_tuple *t)
{
	struct nfattr *nest;

	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_IP);

	switch(t->l3protonum) {
	case AF_INET:
	        nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_SRC, &t->src.v4,
			       sizeof(u_int32_t));
		nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_DST, &t->dst.v4,
			       sizeof(u_int32_t));
		break;
	case AF_INET6:
		nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_SRC, &t->src.v6,
			       sizeof(struct in6_addr));
		nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_DST, &t->dst.v6,
			       sizeof(struct in6_addr));
		break;
	default:
		break;
	}

	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 2
0
void __build_dnat_port(struct nfnlhdr *req,
		       size_t size, 
		       const struct nf_conntrack *ct)
{
	struct nfattr *nest;

	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
        __build_protonat(req, size, ct, &ct->dnat);
	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 3
0
void __build_snat_ipv4(struct nfnlhdr *req,
		       size_t size,
		       const struct nf_conntrack *ct)
{
	struct nfattr *nest;

	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
	__build_nat(req, size, &ct->snat);
	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 4
0
void __build_tuple(struct nfnlhdr *req, 
		   size_t size, 
		   const struct __nfct_tuple *t, 
		   const int type)
{
	struct nfattr *nest;

	nest = nfnl_nest(&req->nlh, size, type);

	__build_tuple_ip(req, size, t);
	__build_tuple_proto(req, size, t);

	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 5
0
void __build_helper_name(struct nfnlhdr *req,
			 size_t size,
			 const struct nf_conntrack *ct)
{
	struct nfattr *nest;

	nest = nfnl_nest(&req->nlh, size, CTA_HELP);
	nfnl_addattr_l(&req->nlh,
		       size, 
		       CTA_HELP_NAME,
		       ct->helper_name,
		       strlen(ct->helper_name));
	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 6
0
static void 
__build_nat_seq_adj(struct nfnlhdr *req, 
		    size_t size,
		    const struct nf_conntrack *ct,
		    int dir)
{
	struct nfattr *nest;
	int type = (dir == __DIR_ORIG) ? CTA_NAT_SEQ_ADJ_ORIG : 
					 CTA_NAT_SEQ_ADJ_REPLY;

	nest = nfnl_nest(&req->nlh, size, type);
	__nat_seq_adj(req, size, ct, dir);
	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 7
0
void __build_tuple_proto(struct nfnlhdr *req,
			 size_t size,
			 const struct __nfct_tuple *t)
{
	struct nfattr *nest;

	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_PROTO);

	nfnl_addattr_l(&req->nlh, size, CTA_PROTO_NUM, &t->protonum,
		       sizeof(u_int8_t));

	switch(t->protonum) {
	case IPPROTO_UDP:
	case IPPROTO_TCP:
	case IPPROTO_SCTP:
	case IPPROTO_DCCP:
	case IPPROTO_GRE:
	case IPPROTO_UDPLITE:
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
			       &t->l4src.tcp.port, sizeof(u_int16_t));
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
			       &t->l4dst.tcp.port, sizeof(u_int16_t));
		break;

	case IPPROTO_ICMP:
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_CODE,
			       &t->l4dst.icmp.code, sizeof(u_int8_t));
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_TYPE,
			       &t->l4dst.icmp.type, sizeof(u_int8_t));
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_ID,
			       &t->l4src.icmp.id, sizeof(u_int16_t));
		break;

	case IPPROTO_ICMPV6:
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMPV6_CODE,
			       &t->l4dst.icmp.code, sizeof(u_int8_t));
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMPV6_TYPE,
			       &t->l4dst.icmp.type, sizeof(u_int8_t));
		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMPV6_ID,
			       &t->l4src.icmp.id, sizeof(u_int16_t));
		break;

	default:
		break;
	}

	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 8
0
void __build_protonat(struct nfnlhdr *req,
		      size_t size,
		      const struct nf_conntrack *ct,
		      const struct __nfct_nat *nat)
{
	struct nfattr *nest;

	nest = nfnl_nest(&req->nlh, size, CTA_NAT_PROTO);

	switch (ct->tuple[__DIR_ORIG].protonum) {
	case IPPROTO_TCP:
	case IPPROTO_UDP:
		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_PORT_MIN,
			       &nat->l4min.tcp.port, sizeof(u_int16_t));
		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_PORT_MAX,
			       &nat->l4max.tcp.port, sizeof(u_int16_t));
		break;
	}
	nfnl_nest_end(&req->nlh, nest);
}
Esempio n. 9
0
static void __build_protoinfo(struct nfnlhdr *req, size_t size,
			      const struct nf_conntrack *ct)
{
	struct nfattr *nest, *nest_proto;

	switch(ct->tuple[__DIR_ORIG].protonum) {
	case IPPROTO_TCP:
		nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP);
		if (test_bit(ATTR_TCP_STATE, ct->set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_STATE,
				       &ct->protoinfo.tcp.state,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_TCP_FLAGS_ORIG, ct->set) &&
		    test_bit(ATTR_TCP_MASK_ORIG, ct->set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
				       &ct->protoinfo.tcp.flags[0], 
				       sizeof(u_int16_t));
		if (test_bit(ATTR_TCP_FLAGS_REPL, ct->set) &&
		    test_bit(ATTR_TCP_MASK_REPL, ct->set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_FLAGS_REPLY,
				       &ct->protoinfo.tcp.flags[1], 
				       sizeof(u_int16_t));
		nfnl_nest_end(&req->nlh, nest_proto);
		nfnl_nest_end(&req->nlh, nest);
		break;
	case IPPROTO_SCTP:
		nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_SCTP);
		if (test_bit(ATTR_SCTP_STATE, ct->set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_SCTP_STATE,
				       &ct->protoinfo.sctp.state,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_SCTP_VTAG_ORIG, ct->set))
			nfnl_addattr32(&req->nlh, size,
				    CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
				    htonl(ct->protoinfo.sctp.vtag[__DIR_ORIG]));
		if (test_bit(ATTR_SCTP_VTAG_REPL, ct->set))
			nfnl_addattr32(&req->nlh, size,
				    CTA_PROTOINFO_SCTP_VTAG_REPLY,
				    htonl(ct->protoinfo.sctp.vtag[__DIR_REPL]));
		nfnl_nest_end(&req->nlh, nest_proto);
		nfnl_nest_end(&req->nlh, nest);
		break;
	case IPPROTO_DCCP:
		nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_DCCP);
		if (test_bit(ATTR_DCCP_STATE, ct->set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_DCCP_STATE,
				       &ct->protoinfo.dccp.state,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_DCCP_ROLE, ct->set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_DCCP_ROLE,
				       &ct->protoinfo.dccp.role,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->set)) {
			/* FIXME: use __cpu_to_be64() instead which is the
			 * correct operation. This is a semantic abuse but
			 * we have no function to do it in libnfnetlink. */
			u_int64_t handshake_seq =
				__be64_to_cpu(ct->protoinfo.dccp.handshake_seq);

			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_DCCP_SEQ,
				       &handshake_seq,
				       sizeof(u_int64_t));
		}
		nfnl_nest_end(&req->nlh, nest_proto);
		nfnl_nest_end(&req->nlh, nest);
	default:
		break;
	}
}
Esempio n. 10
0
static void __build_protoinfo(struct nfnlhdr *req, size_t size,
			      const struct nf_conntrack *ct)
{
	struct nfattr *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 = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP);
		if (test_bit(ATTR_TCP_STATE, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_STATE,
				       &ct->protoinfo.tcp.state,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_TCP_FLAGS_ORIG, ct->head.set) &&
		    test_bit(ATTR_TCP_MASK_ORIG, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
				       &ct->protoinfo.tcp.flags[0], 
				       sizeof(struct nf_ct_tcp_flags));
		if (test_bit(ATTR_TCP_FLAGS_REPL, ct->head.set) &&
		    test_bit(ATTR_TCP_MASK_REPL, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_FLAGS_REPLY,
				       &ct->protoinfo.tcp.flags[1], 
				       sizeof(struct nf_ct_tcp_flags));
		if (test_bit(ATTR_TCP_WSCALE_ORIG, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
				       &ct->protoinfo.tcp.wscale[__DIR_ORIG],
				       sizeof(u_int8_t));
		if (test_bit(ATTR_TCP_WSCALE_REPL, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_TCP_WSCALE_REPLY,
				       &ct->protoinfo.tcp.wscale[__DIR_REPL],
				       sizeof(u_int8_t));
		nfnl_nest_end(&req->nlh, nest_proto);
		nfnl_nest_end(&req->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 = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_SCTP);
		if (test_bit(ATTR_SCTP_STATE, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_SCTP_STATE,
				       &ct->protoinfo.sctp.state,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_SCTP_VTAG_ORIG, ct->head.set))
			nfnl_addattr32(&req->nlh, size,
				    CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
				    htonl(ct->protoinfo.sctp.vtag[__DIR_ORIG]));
		if (test_bit(ATTR_SCTP_VTAG_REPL, ct->head.set))
			nfnl_addattr32(&req->nlh, size,
				    CTA_PROTOINFO_SCTP_VTAG_REPLY,
				    htonl(ct->protoinfo.sctp.vtag[__DIR_REPL]));
		nfnl_nest_end(&req->nlh, nest_proto);
		nfnl_nest_end(&req->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 = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_DCCP);
		if (test_bit(ATTR_DCCP_STATE, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_DCCP_STATE,
				       &ct->protoinfo.dccp.state,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_DCCP_ROLE, ct->head.set))
			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_DCCP_ROLE,
				       &ct->protoinfo.dccp.role,
				       sizeof(u_int8_t));
		if (test_bit(ATTR_DCCP_HANDSHAKE_SEQ, ct->head.set)) {
			/* FIXME: use __cpu_to_be64() instead which is the
			 * correct operation. This is a semantic abuse but
			 * we have no function to do it in libnfnetlink. */
			u_int64_t handshake_seq =
				__be64_to_cpu(ct->protoinfo.dccp.handshake_seq);

			nfnl_addattr_l(&req->nlh, size,
				       CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
				       &handshake_seq,
				       sizeof(u_int64_t));
		}
		nfnl_nest_end(&req->nlh, nest_proto);
		nfnl_nest_end(&req->nlh, nest);
	default:
		break;
	}
}