Esempio n. 1
0
void print_snatlog(struct nf_conntrack *ct, 
      time_t *timestamp, char *proto_str) {
   int ret = 0, size = 0, offset = 0, len = BUF_LEN;
   char buf[BUF_LEN];

   ret = __snprintf_start_log(buf, len, "SNAT_LOG");
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " proto=%s", proto_str);
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " o-src=%s",
         net2addr(nfct_get_attr_u32(ct,ATTR_ORIG_IPV4_SRC)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " o-spt=%d",
         ntohs(nfct_get_attr_u16(ct,ATTR_ORIG_PORT_SRC)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " t-src=%s",
         net2addr(nfct_get_attr_u32(ct,ATTR_REPL_IPV4_DST)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " t-spt=%d",
         ntohs(nfct_get_attr_u16(ct,ATTR_REPL_PORT_DST)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " duration=%.0lfs", 
         difftime(time(NULL),*timestamp));
   BUFFER_SIZE(ret, size, len, offset);

   buf[size+1 > len ? len-1 : size] = '\0';

   write_msg(LOG_INFO, buf);
}
Esempio n. 2
0
static inline void 
ct_build_u32(const struct nf_conntrack *ct, int a, struct nethdr *n, int b)
{
	uint32_t data = nfct_get_attr_u32(ct, a);
	data = htonl(data);
	addattr(n, b, &data, sizeof(uint32_t));
}
Esempio n. 3
0
static int callback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data)
{
  unsigned int *ret = (unsigned int *)data;
  *ret = nfct_get_attr_u32(ct, ATTR_MARK);
  (void)type; /* eliminate warning */
  gotit = 1;

  return NFCT_CB_CONTINUE;
}
static PyObject*
get_attr32(struct nf_conntrack *ct, int attrid, int ntoh)
{
    uint32_t value;
    value = nfct_get_attr_u32(ct, attrid);
    if (ntoh)
        value = ntohl(value);
    return PyLong_FromUnsignedLong(value);
}
Esempio n. 5
0
static int event_cb(enum nf_conntrack_msg_type type,
		    struct nf_conntrack *ct,
		    void *data) {
   struct conntrack_list *no;
   u_int8_t l4proto;

   // we are interested only in SNAT connections
   if (!nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT))
      return NFCT_CB_CONTINUE;

   // We are interested only in TCP/UDP L4 protocols...
   l4proto = nfct_get_attr_u8(ct,ATTR_ORIG_L4PROTO);
   if (l4proto != IPPROTO_TCP && l4proto != IPPROTO_UDP)
      return NFCT_CB_CONTINUE;

   if (verbose_flag) {
      print_verbose(ct, type, proto_str(l4proto));
   }

   switch(type) {
      case NFCT_T_NEW:
         no = (struct conntrack_list *)malloc(sizeof(struct conntrack_list));
         no->id = nfct_get_attr_u32(ct,ATTR_ID);
         no->orig_ipv4_src = nfct_get_attr_u32(ct,ATTR_ORIG_IPV4_SRC);
         no->orig_port_src = nfct_get_attr_u16(ct,ATTR_ORIG_PORT_SRC);
         time(&no->timestamp);
         list_add(&ct_list, no);
         break;
      case NFCT_T_DESTROY:
         no = list_find(ct_list,
               nfct_get_attr_u32(ct,ATTR_ID),
               nfct_get_attr_u32(ct,ATTR_ORIG_IPV4_SRC),
               nfct_get_attr_u16(ct,ATTR_ORIG_PORT_SRC));
         if (no) {
            print_snatlog(ct, &no->timestamp, proto_str(l4proto));
            list_del(&ct_list,no);
         }
         break;
      default:
         break;
   }

   return NFCT_CB_CONTINUE;
}
Esempio n. 6
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;
}
static void
__do_commit_step(struct __commit_container *tmp, struct cache_object *obj)
{
	int ret, retry = 1, timeout;
	struct nf_conntrack *ct = obj->ct;

	if (CONFIG(commit_timeout)) {
		timeout = CONFIG(commit_timeout);
	} else {
		timeout = time(NULL) - obj->lastupdate;
		if (timeout < 0) {
			/* XXX: Arbitrarily set the timer to one minute, how
			 * can this happen? For example, an adjustment due to
			 * daylight-saving. Probably other situations can
			 * trigger this. */
			timeout = 60;
		}
		/* calculate an estimation of the current timeout */
		timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT) - timeout;
		if (timeout < 0) {
			timeout = 60;
		}
	}

retry:
	if (nl_create_conntrack(tmp->h, ct, timeout) == -1) {
		if (errno == EEXIST && retry == 1) {
			ret = nl_destroy_conntrack(tmp->h, ct);
			if (ret == 0 || (ret == -1 && errno == ENOENT)) {
				if (retry) {
					retry = 0;
					goto retry;
				}
			}
			dlog(LOG_ERR, "commit-destroy: %s", strerror(errno));
			dlog_ct(STATE(log), ct, NFCT_O_PLAIN);
			tmp->c->stats.commit_fail++;
		} else {
			dlog(LOG_ERR, "commit-create: %s", strerror(errno));
			dlog_ct(STATE(log), ct, NFCT_O_PLAIN);
			tmp->c->stats.commit_fail++;
		}
	} else {
		tmp->c->stats.commit_ok++;
	}
}
Esempio n. 8
0
static int data_cb(const struct nlmsghdr *nlh, void *data)
{
	struct nf_conntrack *ct;
	struct data_cb_s * d = (struct data_cb_s*) data;
	struct sockaddr_in* ext4 = (struct sockaddr_in*) d->ext;

	ct = nfct_new();
	if (ct == NULL)
		return MNL_CB_OK;
	nfct_nlmsg_parse(nlh, ct);

	if (data) {
		ext4->sin_addr.s_addr = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST);
		ext4->sin_port =        nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
	}
	d->found = 1;
	nfct_destroy(ct);

	return MNL_CB_OK;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
static int
rpc_helper_cb(struct pkt_buff *pkt, uint32_t protoff,
	      struct myct *myct, uint32_t ctinfo)
{
	int dir = CTINFO2DIR(ctinfo);
	unsigned int offset = protoff, datalen;
	uint32_t *data, *port_ptr = NULL, xid;
	uint16_t port;
	uint8_t proto = nfct_get_attr_u8(myct->ct, ATTR_L4PROTO);
	enum msg_type rm_dir;
	struct rpc_info *rpc_info = myct->priv_data;
	union nfct_attr_grp_addr addr, daddr;
	struct nf_expect *exp = NULL;
	int ret = NF_ACCEPT;

	/* Until there's been traffic both ways, don't look into TCP packets. */
	if (proto == IPPROTO_TCP
	    && ctinfo != IP_CT_ESTABLISHED
	    && ctinfo != IP_CT_ESTABLISHED_REPLY) {
		pr_debug("TCP RPC: Conntrackinfo = %u\n", ctinfo);
		return ret;
	}
	if (proto == IPPROTO_TCP) {
		struct tcphdr *th =
			(struct tcphdr *) (pktb_network_header(pkt) + protoff);
		offset += th->doff * 4;
	} else {
		offset += sizeof(struct udphdr);
	}
	/* Skip broken headers */
	if (offset % 4) {
		pr_debug("RPC: broken header: offset %u%%4 != 0\n", offset);
		return ret;
	}

	/* Take into Record Fragment header */
	if (proto == IPPROTO_TCP)
		offset += 4;

	datalen = pktb_len(pkt);
	data = (uint32_t *)(pktb_network_header(pkt) + offset);

	/* rpc_msg {
	 *	xid
	 *	direction
	 *	xdr_union {
	 *		call_body
	 *		reply_body
	 *	}
	 * }
	 */

	 /* Check minimal msg size: xid + direction */
	if (datalen < OFFSET(offset, 2*4)) {
		pr_debug("RPC: too short packet: %u < %u\n",
			 datalen, offset);
		return ret;
	}
	xid = IXDR_GET_INT32(data);
	rm_dir = IXDR_GET_INT32(data);

	/* Check direction */
	if (!((rm_dir == CALL && dir == MYCT_DIR_ORIG)
	      || (rm_dir == REPLY && dir == MYCT_DIR_REPL))) {
		pr_debug("RPC: rm_dir != dir %u != %u\n", rm_dir, dir);
		goto out;
	}

	if (rm_dir == CALL) {
		if (rpc_call(data, offset, datalen, rpc_info) < 0)
			goto out;

		rpc_info->xid = xid;

		return ret;
	} else {
		/* Check XID */
		if (xid != rpc_info->xid) {
			pr_debug("RPC REPL: XID does not match: %u != %u\n",
				 xid, rpc_info->xid);
			goto out;
		}
		if (rpc_reply(data, offset, datalen, rpc_info, &port_ptr) < 0)
			goto out;

		port = IXDR_GET_INT32(port_ptr);
		port = htons(port);

		/* We refer to the reverse direction ("!dir") tuples here,
		 * because we're expecting something in the other direction.
		 * Doesn't matter unless NAT is happening.  */
		cthelper_get_addr_dst(myct->ct, !dir, &daddr);
		cthelper_get_addr_src(myct->ct, !dir, &addr);

		exp = nfexp_new();
		if (exp == NULL)
			goto out;

		if (cthelper_expect_init(exp, myct->ct, 0, &addr, &daddr,
					 rpc_info->pm_prot,
					 NULL, &port, NF_CT_EXPECT_PERMANENT)) {
			pr_debug("RPC: failed to init expectation\n");
			goto out_exp;
		}

		/* Now, NAT might want to mangle the packet, and register the
		 * (possibly changed) expectation itself. */
		if (nfct_get_attr_u32(myct->ct, ATTR_STATUS) & IPS_NAT_MASK) {
			ret = nf_nat_rpc(pkt, dir, exp, rpc_info->pm_prot,
					 port_ptr);
			goto out_exp;
		}

		/* Can't expect this?  Best to drop packet now. */
		if (cthelper_add_expect(exp) < 0) {
			pr_debug("RPC: cannot add expectation: %s\n",
				 strerror(errno));
			ret = NF_DROP;
		}
	}

out_exp:
	nfexp_destroy(exp);
out:
	rpc_info->xid = 0;
	return ret;
}
Esempio n. 11
0
void print_verbose(struct nf_conntrack *ct,
      enum nf_conntrack_msg_type type, char *proto_str) {
   int ret = 0, size = 0, offset = 0, len = BUF_LEN;
   char buf[BUF_LEN];

   ret = __snprintf_start_log(buf, len, "DEBUG");
   BUFFER_SIZE(ret, size, len, offset);

   switch(type) {
      case NFCT_T_NEW:
         ret = snprintf(buf+offset, len, " NEW");
         BUFFER_SIZE(ret, size, len, offset);
         break;
      case NFCT_T_DESTROY:
         ret = snprintf(buf+offset, len, " DESTROY");
         BUFFER_SIZE(ret, size, len, offset);
         break;
      default:
         break;
   }

   ret = snprintf(buf+offset, len, " id=%u", nfct_get_attr_u32(ct,ATTR_ID));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " proto=%s", proto_str);
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " orig-src=%s", 
         net2addr(nfct_get_attr_u32(ct,ATTR_ORIG_IPV4_SRC)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " orig-dst=%s", 
         net2addr(nfct_get_attr_u32(ct,ATTR_ORIG_IPV4_DST)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " orig-sport=%d", 
         ntohs(nfct_get_attr_u16(ct,ATTR_ORIG_PORT_SRC)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " orig-dport=%d", 
         ntohs(nfct_get_attr_u16(ct,ATTR_ORIG_PORT_DST)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " repl-src=%s", 
         net2addr(nfct_get_attr_u32(ct,ATTR_REPL_IPV4_SRC)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " repl-dst=%s", 
         net2addr(nfct_get_attr_u32(ct,ATTR_REPL_IPV4_DST)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " repl-sport=%d", 
         ntohs(nfct_get_attr_u16(ct,ATTR_REPL_PORT_SRC)));
   BUFFER_SIZE(ret, size, len, offset);

   ret = snprintf(buf+offset, len, " repl-dport=%d", 
         ntohs(nfct_get_attr_u16(ct,ATTR_REPL_PORT_DST)));
   BUFFER_SIZE(ret, size, len, offset);

   buf[size+1 > len ? len-1 : size] = '\0';

   write_msg(LOG_INFO, buf);
}
Esempio n. 12
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;
}