static int parse(char c,
		 struct nf_conntrack *ct,
		 struct nf_conntrack *exptuple,
		 struct nf_conntrack *mask,
		 unsigned int *flags)
{
	switch(c) {
		u_int8_t tmp;
		u_int16_t id;
		case '1':
			tmp = atoi(optarg);
			nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, tmp);
			nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMP);
			*flags |= CT_ICMP_TYPE;
			break;
		case '2':
			tmp = atoi(optarg);
			nfct_set_attr_u8(ct, ATTR_ICMP_CODE, tmp);
			nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMP);
			*flags |= CT_ICMP_CODE;
			break;
		case '3':
			id = htons(atoi(optarg));
			nfct_set_attr_u16(ct, ATTR_ICMP_ID, id);
			nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMP);
			*flags |= CT_ICMP_ID;
			break;
	}
	return 1;
}
Exemple #2
0
int main()
{
	int ret;
	struct nfct_handle *h;
	struct nf_conntrack *ct;

	ct = nfct_new();
	if (!ct) {
		perror("nfct_new");
		return 0;
	}

	nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(ct, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
	nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr("2.2.2.2"));
	
	nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20));
	nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10));

	h = nfct_open(CONNTRACK, 0);
	if (!h) {
		perror("nfct_open");
		return -1;
	}

	ret = nfct_query(h, NFCT_Q_DESTROY, ct);

	printf("TEST: delete conntrack (%d)(%s)\n", ret, strerror(errno));

	if (ret == -1)
		exit(EXIT_FAILURE);

	nfct_close(h);
}
Exemple #3
0
static PyObject*
ForwardingRule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    ForwardingRule *self;

    self = (ForwardingRule*) type->tp_alloc(type, 0);
    if (self != NULL) {
        self->is_active = 0;
        self->done_init = 0;
        self->prev = NULL;
        self->next = NULL;
        memset(self->counter, 0, sizeof(uint32_t) * 4);
        if ((self->dict = PyDict_New()) == NULL) {
            Py_DECREF(self);
            return NULL;
        }
        if ((self->conntrack = nfct_new()) == NULL) {
            Py_DECREF(self->dict);
            Py_DECREF(self);
            PyErr_NoMemory();
            return NULL;
        }
        nfct_set_attr_u8(self->conntrack, ATTR_ORIG_L3PROTO, AF_INET);
        nfct_set_attr_u8(self->conntrack, ATTR_ORIG_L4PROTO, IPPROTO_UDP);
    }

    return (PyObject*) self;
}
Exemple #4
0
static void l4_tcp_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct)
{
	const struct tcphdr *tcph = (const struct tcphdr *)pkt;

	nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, tcph->source);
	nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, tcph->dest);
	nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, tcph->dest);
	nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, tcph->source);
}
Exemple #5
0
/* So, this packet has hit the connection tracking matching code.
   Mangle it, and change the expectation to match the new version. */
static unsigned int
nf_nat_rpc(struct pkt_buff *pkt, int dir, struct nf_expect *exp,
	   uint8_t proto, uint32_t *port_ptr)
{
	const struct nf_conntrack *expected;
	struct nf_conntrack *nat_tuple;
	uint16_t initial_port, port;

	expected = nfexp_get_attr(exp, ATTR_EXP_EXPECTED);

	nat_tuple = nfct_new();
	if (nat_tuple == NULL)
		return NF_ACCEPT;

	initial_port = nfct_get_attr_u16(expected, ATTR_PORT_DST);

	nfexp_set_attr_u32(exp, ATTR_EXP_NAT_DIR, !dir);

	/* libnetfilter_conntrack needs this */
	nfct_set_attr_u8(nat_tuple, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(nat_tuple, ATTR_IPV4_SRC, 0);
	nfct_set_attr_u32(nat_tuple, ATTR_IPV4_DST, 0);
	nfct_set_attr_u8(nat_tuple, ATTR_L4PROTO, proto);
	nfct_set_attr_u16(nat_tuple, ATTR_PORT_DST, 0);

	/* When you see the packet, we need to NAT it the same as the
	 * this one. */
	nfexp_set_attr(exp, ATTR_EXP_FN, "nat-follow-master");

	/* Try to get same port: if not, try to change it. */
	for (port = ntohs(initial_port); port != 0; port++) {
		int ret;

		nfct_set_attr_u16(nat_tuple, ATTR_PORT_SRC, htons(port));
		nfexp_set_attr(exp, ATTR_EXP_NAT_TUPLE, nat_tuple);

		ret = cthelper_add_expect(exp);
		if (ret == 0)
			break;
		else if (ret != -EBUSY) {
			port = 0;
			break;
		}
	}
	nfct_destroy(nat_tuple);

	if (port == 0)
		return NF_DROP;

	*port_ptr = htonl(port);

	return NF_ACCEPT;
}
int main(void)
{
	int ret;
	struct nfct_handle *h;
	struct nf_conntrack *expected;
	struct nf_expect *exp;

	expected = nfct_new();
	if (!expected) {
		perror("nfct_new");
		exit(EXIT_FAILURE);
	}

	nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(expected, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
	nfct_set_attr_u32(expected, ATTR_IPV4_DST, inet_addr("2.2.2.2"));

	nfct_set_attr_u8(expected, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0);
	nfct_set_attr_u16(expected, ATTR_PORT_DST, htons(10241));

	exp = nfexp_new();
	if (!exp) {
		perror("nfexp_new");
		nfct_destroy(expected);
		exit(EXIT_FAILURE);
	}

	nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected);

	h = nfct_open(EXPECT, 0);
	if (!h) {
		perror("nfct_open");
		nfct_destroy(expected);
		return -1;
	}

	ret = nfexp_query(h, NFCT_Q_DESTROY, exp);

	printf("TEST: delete expectation ");
	if (ret == -1)
		printf("(%d)(%s)\n", ret, strerror(errno));
	else
		printf("(OK)\n");

	nfct_close(h);

	nfct_destroy(expected);

	ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS);
}
static int parse_options(char c,
			 struct nf_conntrack *ct,
			 struct nf_conntrack *exptuple,
			 struct nf_conntrack *mask,
			 unsigned int *flags)
{
	switch(c) {
	u_int16_t port;
	case '1':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port);
		nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_ORIG_SKEY;
		break;
	case '2':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, port);
		nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_ORIG_DKEY;
		break;
	case '3':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, port);
		nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_REPL_SKEY;
		break;
	case '4':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, port);
		nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_REPL_DKEY;
		break;
	case '5':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(mask, ATTR_ORIG_PORT_SRC, port);
		nfct_set_attr_u8(mask, ATTR_ORIG_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_MASK_SKEY;
		break;
	case '6':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(mask, ATTR_ORIG_PORT_DST, port);
		nfct_set_attr_u8(mask, ATTR_ORIG_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_MASK_DKEY;
		break;
	case '7':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(exptuple, ATTR_ORIG_PORT_SRC, port);
		nfct_set_attr_u8(exptuple, ATTR_ORIG_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_EXPTUPLE_SKEY;
		break;
	case '8':
		port = htons(strtoul(optarg, NULL, 0));
		nfct_set_attr_u16(exptuple, ATTR_ORIG_PORT_DST, port);
		nfct_set_attr_u8(exptuple, ATTR_ORIG_L4PROTO, IPPROTO_GRE);
		*flags |= CT_GRE_EXPTUPLE_DKEY;
		break;
	}
	return 1;
}
Exemple #8
0
int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr, int istcp, unsigned int *markp)
{
  struct nf_conntrack *ct;
  struct nfct_handle *h;
  
  gotit = 0;
  
  if ((ct = nfct_new())) 
    {
      nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP);
      nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port));
      
#ifdef HAVE_IPV6
      if (peer_addr->sa.sa_family == AF_INET6)
	{
	  nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6);
	  nfct_set_attr(ct, ATTR_IPV6_SRC, peer_addr->in6.sin6_addr.s6_addr);
	  nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in6.sin6_port);
	  nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr.addr6.s6_addr);
	}
      else
#endif
	{
	  nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
	  nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr);
	  nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in.sin_port);
	  nfct_set_attr_u32(ct, ATTR_IPV4_DST, local_addr->addr.addr4.s_addr);
	}
      
      
      if ((h = nfct_open(CONNTRACK, 0))) 
	{
	  nfct_callback_register(h, NFCT_T_ALL, callback, (void *)markp);  
	  if (nfct_query(h, NFCT_Q_GET, ct) == -1)
	    {
	      static int warned = 0;
	      if (!warned)
		{
		  my_syslog(LOG_ERR, _("Conntrack connection mark retrieval failed: %s"), strerror(errno));
		  warned = 1;
		}
	    }
	  nfct_close(h);  
	}
      nfct_destroy(ct);
    }

  return gotit;
}
Exemple #9
0
int nl_create_conntrack(struct nfct_handle *h, 
			const struct nf_conntrack *orig,
			int timeout)
{
	int ret;
	struct nf_conntrack *ct;

	ct = nfct_clone(orig);
	if (ct == NULL)
		return -1;

	if (timeout > 0)
		nfct_set_attr_u32(ct, ATTR_TIMEOUT, timeout);

	/* we hit error if we try to change the expected bit */
	if (nfct_attr_is_set(ct, ATTR_STATUS)) {
		uint32_t status = nfct_get_attr_u32(ct, ATTR_STATUS);
		status &= ~IPS_EXPECTED;
		nfct_set_attr_u32(ct, ATTR_STATUS, status);
	}

	nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY);

	/* disable TCP window tracking for recovered connections if required */
	if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) {
		uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM;

		if (!CONFIG(sync).tcp_window_tracking)
			flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
		else
			flags |= IP_CT_TCP_FLAG_WINDOW_SCALE;

		/* FIXME: workaround, we should send TCP flags in updates */
		if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >=
						TCP_CONNTRACK_TIME_WAIT) {
			flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
		}
		nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
	}

	ret = nfct_query(h, NFCT_Q_CREATE, ct);
	nfct_destroy(ct);

	return ret;
}
Exemple #10
0
int main()
{
	int ret;
	struct nfct_handle *h;
	struct nf_conntrack *ct;

	ct = nfct_new();
	if (!ct) {
		perror("nfct_new");
		return 0;
	}

	nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(ct, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
	nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr("2.2.2.2"));
	
	nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20));
	nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10));

	nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY);

	nfct_set_attr_u8(ct, ATTR_TCP_STATE, TCP_CONNTRACK_LISTEN);
	nfct_set_attr_u32(ct, ATTR_TIMEOUT, 100);

	nfct_set_attr_u32(ct, ATTR_SNAT_IPV4, inet_addr("8.8.8.8"));

	h = nfct_open(CONNTRACK, 0);
	if (!h) {
		perror("nfct_open");
		return -1;
	}

	ret = nfct_query(h, NFCT_Q_CREATE, ct);

	printf("TEST: create conntrack (%d)(%s)\n", ret, strerror(errno));

	if (ret == -1)
		exit(EXIT_FAILURE);

	nfct_close(h);
}
static int test_nfct_cmp_api_single(struct nf_conntrack *ct1,
				struct nf_conntrack *ct2, int attr)
{
	char data[256];
	struct nfct_bitmask *b;
	int bit;

	if (attr_is_readonly(attr))
		return 0;

	switch (attr) {
	case ATTR_SECMARK: /* obsolete */
		return 0;

	/* FIXME: not implemented comparators: */
	case ATTR_SNAT_IPV4:
	case ATTR_DNAT_IPV4:
	case ATTR_SNAT_PORT:
	case ATTR_DNAT_PORT:

	case ATTR_TCP_FLAGS_ORIG:
	case ATTR_TCP_FLAGS_REPL:
	case ATTR_TCP_MASK_ORIG:
	case ATTR_TCP_MASK_REPL:

	case ATTR_MASTER_IPV4_SRC:
	case ATTR_MASTER_IPV4_DST:
	case ATTR_MASTER_IPV6_SRC:
	case ATTR_MASTER_IPV6_DST:
	case ATTR_MASTER_PORT_SRC:
	case ATTR_MASTER_PORT_DST:
	case ATTR_MASTER_L3PROTO:
	case ATTR_MASTER_L4PROTO:

	case ATTR_ORIG_NAT_SEQ_CORRECTION_POS:
	case ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE:
	case ATTR_ORIG_NAT_SEQ_OFFSET_AFTER:
	case ATTR_REPL_NAT_SEQ_CORRECTION_POS:
	case ATTR_REPL_NAT_SEQ_OFFSET_BEFORE:
	case ATTR_REPL_NAT_SEQ_OFFSET_AFTER:

	case ATTR_SCTP_VTAG_ORIG:
	case ATTR_SCTP_VTAG_REPL:

	case ATTR_HELPER_NAME:

	case ATTR_DCCP_ROLE:
	case ATTR_DCCP_HANDSHAKE_SEQ:

	case ATTR_TCP_WSCALE_ORIG:
	case ATTR_TCP_WSCALE_REPL:

	case ATTR_HELPER_INFO:
		return 0; /* XXX */

	default:
		break;
	}

	if (attr >= ATTR_SCTP_STATE) {
		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_SCTP);
		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_SCTP);
	} else if (attr >= ATTR_TCP_FLAGS_ORIG) {
		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP);
		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP);
	} else if (attr >= ATTR_ICMP_CODE) {
		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_ICMP);
		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_ICMP);
	} else if (attr >= ATTR_ORIG_PORT_SRC) {
		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP);
		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP);
	}

	nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE);
	memset(data, 42, sizeof(data));

	assert(nfct_attr_is_set(ct1, attr));
	assert(nfct_attr_is_set(ct2, attr));

	switch (attr) {
	case ATTR_CONNLABELS:
	case ATTR_CONNLABELS_MASK:
		b = (void *) nfct_get_attr(ct1, attr);
		assert(b);
		b = nfct_bitmask_clone(b);
		assert(b);
		bit = nfct_bitmask_maxbit(b);
		if (nfct_bitmask_test_bit(b, bit)) {
			nfct_bitmask_unset_bit(b, bit);
			assert(!nfct_bitmask_test_bit(b, bit));
		} else {
			nfct_bitmask_set_bit(b, bit);
			assert(nfct_bitmask_test_bit(b, bit));
		}
		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
		nfct_set_attr(ct2, attr, b);
		break;
	case ATTR_HELPER_INFO:
		nfct_set_attr_l(ct2, attr, "test", 4);
		break;
	default:
		nfct_set_attr(ct2, attr, data);
		break;
	}

	if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL) != 0) {
		fprintf(stderr, "nfct_cmp assert failure for attr %d\n", attr);
		fprintf(stderr, "%p, %p, %x, %x\n", nfct_get_attr(ct1, attr),
				nfct_get_attr(ct2, attr),
				nfct_get_attr_u32(ct1, attr), nfct_get_attr_u32(ct2, attr));
		return -1;
	}
	if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) != 0) {
		fprintf(stderr, "nfct_cmp strict assert failure for attr %d\n", attr);
		return -1;
	}
	return 0;
}
int main(void)
{
	struct mnl_socket *nl;
	struct nlmsghdr *nlh;
	struct nfgenmsg *nfh;
	char buf[MNL_SOCKET_BUFFER_SIZE];
	unsigned int seq, portid;
	struct nf_conntrack *ct;
	int ret;

	nl = mnl_socket_open(NETLINK_NETFILTER);
	if (nl == NULL) {
		perror("mnl_socket_open");
		exit(EXIT_FAILURE);
	}

	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
		perror("mnl_socket_bind");
		exit(EXIT_FAILURE);
	}
	portid = mnl_socket_get_portid(nl);

	nlh = mnl_nlmsg_put_header(buf);
	nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_DELETE;
	nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
	nlh->nlmsg_seq = seq = time(NULL);

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

	ct = nfct_new();
	if (ct == NULL) {
		perror("nfct_new");
		return 0;
	}

	nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(ct, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
	nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr("2.2.2.2"));

	nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20));
	nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10));

	nfct_nlmsg_build(nlh, ct);

	ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
	if (ret == -1) {
		perror("mnl_socket_recvfrom");
		exit(EXIT_FAILURE);
	}

	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
	while (ret > 0) {
		ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
		if (ret <= MNL_CB_STOP)
			break;
		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
	}
	if (ret == -1) {
		perror("mnl_socket_recvfrom");
		exit(EXIT_FAILURE);
	}

	mnl_socket_close(nl);

	return 0;
}
Exemple #13
0
int nl_update_conntrack(struct nfct_handle *h,
			const struct nf_conntrack *orig,
			int timeout)
{
	int ret;
	struct nf_conntrack *ct;

	ct = nfct_clone(orig);
	if (ct == NULL)
		return -1;

	if (timeout > 0)
		nfct_set_attr_u32(ct, ATTR_TIMEOUT, timeout);

	/* unset NAT info, otherwise we hit error */
	nfct_attr_unset(ct, ATTR_SNAT_IPV4);
	nfct_attr_unset(ct, ATTR_DNAT_IPV4);
	nfct_attr_unset(ct, ATTR_SNAT_PORT);
	nfct_attr_unset(ct, ATTR_DNAT_PORT);

	if (nfct_attr_is_set(ct, ATTR_STATUS)) {
		uint32_t status = nfct_get_attr_u32(ct, ATTR_STATUS);
		status &= ~IPS_NAT_MASK;
		nfct_set_attr_u32(ct, ATTR_STATUS, status);
	}
	/* we have to unset the helper to avoid EBUSY in reset timers */
	if (nfct_attr_is_set(ct, ATTR_HELPER_NAME))
		nfct_attr_unset(ct, ATTR_HELPER_NAME);

	/* we hit error if we try to update the master conntrack */
	if (ct_is_related(ct)) {
		nfct_attr_unset(ct, ATTR_MASTER_L3PROTO);
		nfct_attr_unset(ct, ATTR_MASTER_L4PROTO);
		nfct_attr_unset(ct, ATTR_MASTER_IPV4_SRC);
		nfct_attr_unset(ct, ATTR_MASTER_IPV4_DST);
		nfct_attr_unset(ct, ATTR_MASTER_IPV6_SRC);
		nfct_attr_unset(ct, ATTR_MASTER_IPV6_DST);
		nfct_attr_unset(ct, ATTR_MASTER_PORT_SRC);
		nfct_attr_unset(ct, ATTR_MASTER_PORT_DST);
	}

	/* disable TCP window tracking for recovered connections if required */
	if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) {
		uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM;

		if (!CONFIG(sync).tcp_window_tracking)
			flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
		else
			flags |= IP_CT_TCP_FLAG_WINDOW_SCALE;

		/* FIXME: workaround, we should send TCP flags in updates */
		if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >=
						TCP_CONNTRACK_TIME_WAIT) {
			flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
		}
		nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags);
		nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags);
	}

	ret = nfct_query(h, NFCT_Q_UPDATE, ct);
	nfct_destroy(ct);

	return ret;
}
int main(void)
{
	int ret;
	struct nfct_handle *h;
	struct nf_conntrack *master, *expected, *mask, *nat;
	struct nf_expect *exp;

	/*
	 * Step 1: Setup master conntrack
	 */

	master = nfct_new();
	if (!master) {
		perror("nfct_new");
		exit(EXIT_FAILURE);
	}

	nfct_set_attr_u8(master, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(master, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
	nfct_set_attr_u32(master, ATTR_IPV4_DST, inet_addr("2.2.2.2"));

	nfct_set_attr_u8(master, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(master, ATTR_PORT_SRC, htons(1025));
	nfct_set_attr_u16(master, ATTR_PORT_DST, htons(21));

	nfct_setobjopt(master, NFCT_SOPT_SETUP_REPLY);

	nfct_set_attr_u8(master, ATTR_TCP_STATE, TCP_CONNTRACK_ESTABLISHED);
	nfct_set_attr_u32(master, ATTR_TIMEOUT, 200);
	nfct_set_attr(master, ATTR_HELPER_NAME, "ftp");

	h = nfct_open(CONNTRACK, 0);
	if (!h) {
		perror("nfct_open");
		nfct_destroy(master);
		return -1;
	}

	ret = nfct_query(h, NFCT_Q_CREATE, master);

	printf("TEST: add master conntrack ");
	if (ret == -1)
		printf("(%d)(%s)\n", ret, strerror(errno));
	else
		printf("(OK)\n");

	nfct_close(h);

	expected = nfct_new();
	if (!expected) {
		perror("nfct_new");
		exit(EXIT_FAILURE);
	}

	nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(expected, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
	nfct_set_attr_u32(expected, ATTR_IPV4_DST, inet_addr("2.2.2.2"));

	nfct_set_attr_u8(expected, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0);
	nfct_set_attr_u16(expected, ATTR_PORT_DST, htons(10241));

	mask = nfct_new();
	if (!mask) {
		perror("nfct_new");
		nfct_destroy(master);
		nfct_destroy(expected);
		exit(EXIT_FAILURE);
	}

	nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0xffffffff);
	nfct_set_attr_u32(mask, ATTR_IPV4_DST, 0xffffffff);

	nfct_set_attr_u8(mask, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0x0000);
	nfct_set_attr_u16(mask, ATTR_PORT_DST, 0xffff);

	nat = nfct_new();
	if (!nat) {
		perror("nfct_new");
		nfct_destroy(mask);
		nfct_destroy(master);
		nfct_destroy(expected);
		exit(EXIT_FAILURE);
	}

	nfct_set_attr_u8(nat, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(nat, ATTR_IPV4_SRC, inet_addr("3.3.3.3"));
	nfct_set_attr_u32(nat, ATTR_IPV4_DST, 0);

	nfct_set_attr_u8(nat, ATTR_L4PROTO, IPPROTO_TCP);
	nfct_set_attr_u16(nat, ATTR_PORT_SRC, 12345);
	nfct_set_attr_u16(nat, ATTR_PORT_DST, 0);

	/*
	 * Step 2: Setup expectation
	 */

	exp = nfexp_new();
	if (!exp) {
		perror("nfexp_new");
		nfct_destroy(master);
		nfct_destroy(expected);
		nfct_destroy(mask);
		exit(EXIT_FAILURE);
	}

	nfexp_set_attr(exp, ATTR_EXP_MASTER, master);
	nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected);
	nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
	nfexp_set_attr(exp, ATTR_EXP_NAT_TUPLE, nat);
	nfexp_set_attr_u32(exp, ATTR_EXP_NAT_DIR, 0);
	nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, 200);

	nfct_destroy(master);
	nfct_destroy(expected);
	nfct_destroy(mask);
	nfct_destroy(nat);

	h = nfct_open(EXPECT, 0);
	if (!h) {
		perror("nfct_open");
		return -1;
	}

	ret = nfexp_query(h, NFCT_Q_CREATE, exp);

	printf("TEST: create expectation ");
	if (ret == -1)
		printf("(%d)(%s)\n", ret, strerror(errno));
	else
		printf("(OK)\n");

	nfct_close(h);

	ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS);
}
Exemple #15
0
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto,
                     struct sockaddr_storage* ret_ext)
{
	struct mnl_socket *nl;
	struct nlmsghdr *nlh;
	struct nfgenmsg *nfh;
	char buf[MNL_SOCKET_BUFFER_SIZE];
	unsigned int seq, portid;
	struct nf_conntrack *ct;
	int ret;
	struct data_cb_s data;

	if ((!src)&&(!dst)) {
		return 0;
	}

	if (src->sa_family != dst->sa_family) {
		return 0;
	}

	nl = mnl_socket_open(NETLINK_NETFILTER);
	if (nl == NULL) {
//		perror("mnl_socket_open");
		goto free_nl;
	}

	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
//		perror("mnl_socket_bind");
		goto free_nl;
	}
	portid = mnl_socket_get_portid(nl);

	memset(buf, 0, sizeof(buf));
	nlh = mnl_nlmsg_put_header(buf);
	nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET;
	nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
	nlh->nlmsg_seq = seq = time(NULL);

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

	ct = nfct_new();
	if (ct == NULL) {
		goto free_nl;
	}

	nfct_set_attr_u8(ct, ATTR_L3PROTO, src->sa_family);
	if (src->sa_family == AF_INET) {
		struct sockaddr_in *src4 = (struct sockaddr_in *)src;
		struct sockaddr_in *dst4 = (struct sockaddr_in *)dst;
		nfct_set_attr_u32(ct, ATTR_IPV4_SRC, src4->sin_addr.s_addr);
		nfct_set_attr_u32(ct, ATTR_IPV4_DST, dst4->sin_addr.s_addr);
		nfct_set_attr_u16(ct, ATTR_PORT_SRC, src4->sin_port);
		nfct_set_attr_u16(ct, ATTR_PORT_DST, dst4->sin_port);
	} else if (src->sa_family == AF_INET6) {
		struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src;
		struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
		nfct_set_attr(ct, ATTR_IPV6_SRC, &src6->sin6_addr);
		nfct_set_attr(ct, ATTR_IPV6_DST, &dst6->sin6_addr);
		nfct_set_attr_u16(ct, ATTR_PORT_SRC, src6->sin6_port);
		nfct_set_attr_u16(ct, ATTR_PORT_DST, dst6->sin6_port);
	}
	nfct_set_attr_u8(ct, ATTR_L4PROTO, proto);

	nfct_nlmsg_build(nlh, ct);

	ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
	if (ret == -1) {
		goto free_ct;
	}

	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
	data.ext = ret_ext;
	data.found = 0;
	while (ret > 0) {
		ret = mnl_cb_run(buf, ret, seq, portid, data_cb, &data);
		if (ret <= MNL_CB_STOP)
			break;
		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
	}

free_ct:
    nfct_destroy(ct);
free_nl:
    mnl_socket_close(nl);

	return data.found;
}