static void
print_state(unsigned int statemask)
{
	const char *sep = "";

	if (statemask & IPT_CONNTRACK_STATE_INVALID) {
		printf("%sINVALID", sep);
		sep = ",";
	}
	if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
		printf("%sNEW", sep);
		sep = ",";
	}
	if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
		printf("%sRELATED", sep);
		sep = ",";
	}
	if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
		printf("%sESTABLISHED", sep);
		sep = ",";
	}
	if (statemask & IPT_CONNTRACK_STATE_UNTRACKED) {
		printf("%sUNTRACKED", sep);
		sep = ",";
	}
	if (statemask & IPT_CONNTRACK_STATE_SNAT) {
		printf("%sSNAT", sep);
		sep = ",";
	}
	if (statemask & IPT_CONNTRACK_STATE_DNAT) {
		printf("%sDNAT", sep);
		sep = ",";
	}
	printf(" ");
}
Exemple #2
0
/*
 * Put in -rule- the netfilter rule:
 *
 *  -A POSTROUTING -o ntk_tunl+ -m conntrack
 *  --ctstate NEW -j ntk_mark_chain
 *
 * -rule- has to be NTK_FORWARD_RULE_SZ-sized
 */
void
ntk_forward_rule_init(char *rule)
{
	struct ipt_entry *ee;
	struct ipt_entry_match *em;
	struct ipt_entry_target *et;
	struct ipt_conntrack_info *ici;

	memset(rule, 0, NTK_FORWARD_RULE_SZ);

	ee = (struct ipt_entry *) (rule);
	em = (struct ipt_entry_match *) (rule + IPT_ENTRY_SZ);
	ici = (struct ipt_conntrack_info *) (rule + OFFSET_MATCH_INFO);
	et = (struct ipt_entry_target *) (rule + OFFSET_TARGET);

	ee->next_offset = NTK_FORWARD_RULE_SZ;
	ee->target_offset = OFFSET_TARGET;
	snprintf(ee->ip.outiface, IFNAMSIZ, "%s+", NTK_TUNL_PREFIX);
	memset(ee->ip.outiface_mask, 0xFF, strlen(ee->ip.outiface) - 1);

	strcpy(em->u.user.name, MOD_CONNTRACK);
	em->u.match_size = MATCH_SZ;
	em->u.user.match_size = em->u.match_size;

	ici->flags = 1;
	ici->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_NEW);

	et->u.target_size = IPT_ENTRY_TARGET_SZ + 4;
	et->u.user.target_size = et->u.target_size;
	strcpy(et->u.user.name, NTK_MARK_CHAIN);
}
static int
parse_state(const char *state, size_t strlen, struct ipt_conntrack_info *sinfo)
{
	if (strncasecmp(state, "INVALID", strlen) == 0)
		sinfo->statemask |= IPT_CONNTRACK_STATE_INVALID;
	else if (strncasecmp(state, "NEW", strlen) == 0)
		sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_NEW);
	else if (strncasecmp(state, "ESTABLISHED", strlen) == 0)
		sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
	else if (strncasecmp(state, "RELATED", strlen) == 0)
		sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
	else if (strncasecmp(state, "UNTRACKED", strlen) == 0)
		sinfo->statemask |= IPT_CONNTRACK_STATE_UNTRACKED;
	else if (strncasecmp(state, "SNAT", strlen) == 0)
		sinfo->statemask |= IPT_CONNTRACK_STATE_SNAT;
	else if (strncasecmp(state, "DNAT", strlen) == 0)
		sinfo->statemask |= IPT_CONNTRACK_STATE_DNAT;
	else
		return 0;
	return 1;
}
Exemple #4
0
/*
 * Put in -rule- the netfilter rule:
 *
 *  -A OUTPUT -o ntk_tunl+ -m conntrack  \
 *  --ctstate RELATED,ESTABLISHED -j CONNMARK \
 *  --restore-mark
 *
 * -rule- has to be RESTORE_OUTPUT_RULE_SZ-sized
 */
void
restore_output_rule_init(char *rule)
{
	struct ipt_entry *ee;
	struct ipt_entry_match *em;
	struct ipt_entry_target *et;
	struct ipt_conntrack_info *ici;
	struct ipt_connmark_target_info *icmi;

	memset(rule, 0, RESTORE_OUTPUT_RULE_SZ);

	ee = (struct ipt_entry *) (rule);
	em = (struct ipt_entry_match *) (rule + OFFSET_MATCH);
	ici = (struct ipt_conntrack_info *) (rule + OFFSET_MATCH_INFO);
	et = (struct ipt_entry_target *) (rule + OFFSET_TARGET);
	icmi = (struct ipt_connmark_target_info *) (rule + OFFSET_TARGET_INFO);

	ee->next_offset = RESTORE_OUTPUT_RULE_SZ;
	ee->target_offset = OFFSET_TARGET;

	snprintf(ee->ip.outiface, IFNAMSIZ, "%s+", NTK_TUNL_PREFIX);
	memset(ee->ip.outiface_mask, 0xFF, strlen(ee->ip.outiface) - 1);

	strcpy(em->u.user.name, MOD_CONNTRACK);
	em->u.match_size = MATCH_SZ;;
	em->u.user.match_size = em->u.match_size;

	et->u.target_size = TARGET_SZ;
	et->u.user.target_size = et->u.target_size;
	strcpy(et->u.user.name, MOD_CONNMARK);

	ici->flags = 1;
	ici->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
	ici->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);

	icmi->mode = IPT_CONNMARK_RESTORE;
	icmi->mask = 0xffffffffUL;
}
Exemple #5
0
static int
match(const struct sk_buff *skb,
      const struct net_device *in,
      const struct net_device *out,
      const void *matchinfo,
      int offset,
      const void *hdr,
      u_int16_t datalen,
      int *hotdrop)
{
	const struct ipt_conntrack_info *sinfo = matchinfo;
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	unsigned int statebit;

	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);

#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))

	if (ct)
		statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
	else
		statebit = IPT_CONNTRACK_STATE_INVALID;

	if(sinfo->flags & IPT_CONNTRACK_STATE) {
		if (ct) {
			if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
			    ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip)
				statebit |= IPT_CONNTRACK_STATE_SNAT;

			if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip !=
			    ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)
				statebit |= IPT_CONNTRACK_STATE_DNAT;
		}

		if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE))
			return 0;
	}

	if(sinfo->flags & IPT_CONNTRACK_PROTO) {
		if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO))
                	return 0;
	}

	if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) {
		if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC))
			return 0;
	}

	if(sinfo->flags & IPT_CONNTRACK_ORIGDST) {
		if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST))
			return 0;
	}

	if(sinfo->flags & IPT_CONNTRACK_REPLSRC) {
		if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC))
			return 0;
	}

	if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
		if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST))
			return 0;
	}

	if(sinfo->flags & IPT_CONNTRACK_STATUS) {
		if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS))
			return 0;
	}

	if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
		unsigned long expires;

		if(!ct)
			return 0;

		expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;

		if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES))
			return 0;
	}

	return 1;
}