Пример #1
0
bool oid_in_recovery(uint64_t oid)
{
	struct recovery_work *rw = recovering_work;
	int i;

	if (!node_in_recovery())
		return false;

	if (sd_store->exist(oid)) {
		dprintf("the object %" PRIx64 " is already recoverd\n", oid);
		return false;
	}

	if (before(rw->epoch, sys->epoch))
		return true;

	/* If we are in preparation of object list, oid is not recovered yet */
	if (rw->state == RW_INIT)
		return true;

	/*
	 * Check if oid is in the list that to be recovered later
	 *
	 * FIXME: do we need more efficient yet complex data structure?
	 */
	for (i = rw->done; i < rw->count; i++)
		if (rw->oids[i] == oid)
			break;

	/*
	 * Newly created object after prepare_object_list() might not be
	 * in the list
	 */
	if (i == rw->count) {
		eprintf("%"PRIx64" is not in the recovery list\n", oid);
		return false;
	}

	prepare_schedule_oid(oid);
	return true;
}
Пример #2
0
void memory_model_sct::thread_spawn(
  symex_target_equationt &equation,
  const per_thread_mapt &per_thread_map)
{
  // thread spawn: the spawn precedes the first
  // instruction of the new thread in program order

  unsigned next_thread_id=0;
  for(eventst::const_iterator
      e_it=equation.SSA_steps.begin();
      e_it!=equation.SSA_steps.end();
      e_it++)
  {
    if(is_spawn(e_it))
    {
      per_thread_mapt::const_iterator next_thread=
        per_thread_map.find(++next_thread_id);
      if(next_thread==per_thread_map.end()) continue;

      // For SC and several weaker memory models a memory barrier
      // at the beginning of a thread can simply be ignored, because
      // we enforce program order in the thread-spawn constraint
      // anyway. Memory models with cumulative memory barriers
      // require explicit handling of these.
      event_listt::const_iterator n_it=next_thread->second.begin();
      for( ;
          n_it!=next_thread->second.end() &&
          (*n_it)->is_memory_barrier();
          ++n_it)
        ;

      if(n_it!=next_thread->second.end())
        add_constraint(
          equation,
          before(e_it, *n_it),
          "thread-spawn",
          e_it->source);
    }
  }
}
Пример #3
0
/**
 * Cleans the meta-socket retransmission queue and the reinject-queue.
 * @sk must be the metasocket.
 */
static void mptcp_clean_rtx_queue(struct sock *meta_sk, u32 prior_snd_una)
{
	struct sk_buff *skb, *tmp;
	struct tcp_sock *meta_tp = tcp_sk(meta_sk);
	struct mptcp_cb *mpcb = meta_tp->mpcb;
	int acked = 0;

	while ((skb = tcp_write_queue_head(meta_sk)) &&
	       skb != tcp_send_head(meta_sk)) {
		if (before(meta_tp->snd_una, TCP_SKB_CB(skb)->end_seq))
			break;

		tcp_unlink_write_queue(skb, meta_sk);

		if (mptcp_is_data_fin(skb)) {
			struct sock *sk_it;

			/* DATA_FIN has been acknowledged - now we can close
			 * the subflows
			 */
			mptcp_for_each_sk(mpcb, sk_it) {
				unsigned long delay = 0;

				/* If we are the passive closer, don't trigger
				 * subflow-fin until the subflow has been finned
				 * by the peer - thus we add a delay.
				 */
				if (mpcb->passive_close &&
				    sk_it->sk_state == TCP_ESTABLISHED)
					delay = inet_csk(sk_it)->icsk_rto << 3;

				mptcp_sub_close(sk_it, delay);
			}
		}

		meta_tp->packets_out -= tcp_skb_pcount(skb);
		sk_wmem_free_skb(meta_sk, skb);

		acked = 1;
	}
Пример #4
0
int
arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
	   unsigned long saddr)
{
  struct arp_table *apt;
  PRINTK ("arp_find(haddr=%X, paddr=%X, dev=%X, saddr=%X)\n",
	  haddr, paddr, dev, saddr);
  if (my_ip_addr (paddr))
    {
      memcpy (haddr, dev->dev_addr, dev->addr_len);
      return (0);
    }
  apt = arp_lookup (paddr);
  if (apt != NULL)
    {
       /* make sure it's not too old. If it is too old, we will
	  just pretend we did not find it, and then arp_snd
	  will verify the address for us. */
       if (!before (apt->last_used, timer_seq+ARP_TIMEOUT) &&
	   apt->hlen != 0)
	 {
	    apt->last_used=timer_seq;
	    memcpy (haddr, apt->hard, dev->addr_len);
	    return (0);
	 }
    }

  /* if we didn't find an entry, we will try to 
     send an arp packet. */
  if (apt == NULL || after (timer_seq, apt->last_used+ARP_RES_TIME))
    arp_snd(paddr,dev,saddr);

  /* this assume haddr are atleast 4 bytes.
     If this isn't true we can use a lookup
     table, one for every dev. */
  *(unsigned long *)haddr = paddr;
  return (1);
}
Пример #5
0
/* Setup TCP sequence correction given this change at this sequence */
static inline void
adjust_tcp_sequence(u32 seq,
		    int sizediff,
		    struct nf_conn *ct,
		    enum ip_conntrack_info ctinfo)
{
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	struct nf_conn_nat *nat = nfct_nat(ct);
	struct nf_nat_seq *this_way = &nat->seq[dir];

#ifdef CONFIG_HTC_NETWORK_MODIFY
	if (IS_ERR(this_way) || (!this_way))
		printk(KERN_ERR "[NET] this_way is NULL in %s!\n", __func__);
#endif

	pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n",
		 seq, sizediff);

	pr_debug("adjust_tcp_sequence: Seq_offset before: ");
	DUMP_OFFSET(this_way);

	spin_lock_bh(&nf_nat_seqofs_lock);

	/* SYN adjust. If it's uninitialized, or this is after last
	 * correction, record it: we don't handle more than one
	 * adjustment in the window, but do deal with common case of a
	 * retransmit */
	if (this_way->offset_before == this_way->offset_after ||
	    before(this_way->correction_pos, seq)) {
		this_way->correction_pos = seq;
		this_way->offset_before = this_way->offset_after;
		this_way->offset_after += sizediff;
	}
	spin_unlock_bh(&nf_nat_seqofs_lock);

	pr_debug("adjust_tcp_sequence: Seq_offset after: ");
	DUMP_OFFSET(this_way);
}
Пример #6
0
static void dctcp_update_alpha(struct sock *sk, u32 flags)
{
	const struct tcp_sock *tp = tcp_sk(sk);
	struct dctcp *ca = inet_csk_ca(sk);
	u32 acked_bytes = tp->snd_una - ca->prior_snd_una;

	/* If ack did not advance snd_una, count dupack as MSS size.
	 * If ack did update window, do not count it at all.
	 */
	if (acked_bytes == 0 && !(flags & CA_ACK_WIN_UPDATE))
		acked_bytes = inet_csk(sk)->icsk_ack.rcv_mss;
	if (acked_bytes) {
		ca->acked_bytes_total += acked_bytes;
		ca->prior_snd_una = tp->snd_una;

		if (flags & CA_ACK_ECE)
			ca->acked_bytes_ecn += acked_bytes;
	}

	/* Expired RTT */
	if (!before(tp->snd_una, ca->next_seq)) {
		/* For avoiding denominator == 1. */
		if (ca->acked_bytes_total == 0)
			ca->acked_bytes_total = 1;

		/* alpha = (1 - g) * alpha + g * F */
		ca->dctcp_alpha = ca->dctcp_alpha -
				  (ca->dctcp_alpha >> dctcp_shift_g) +
				  (ca->acked_bytes_ecn << (10U - dctcp_shift_g)) /
				  ca->acked_bytes_total;

		if (ca->dctcp_alpha > DCTCP_MAX_ALPHA)
			/* Clamp dctcp_alpha to max. */
			ca->dctcp_alpha = DCTCP_MAX_ALPHA;

		dctcp_reset(tp, ca);
	}
}
Пример #7
0
/* Setup TCP sequence correction given this change at this sequence */
static inline void
adjust_tcp_sequence(u32 seq,
		    int sizediff,
		    struct nf_conn *ct,
		    enum ip_conntrack_info ctinfo)
{
	int dir;
	struct nf_nat_seq *this_way, *other_way;
	struct nf_conn_nat *nat = nfct_nat(ct);

	pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n",
		 ntohl(seq), seq);

	dir = CTINFO2DIR(ctinfo);

	this_way = &nat->seq[dir];
	other_way = &nat->seq[!dir];

	pr_debug("nf_nat_resize_packet: Seq_offset before: ");
	DUMP_OFFSET(this_way);

	spin_lock_bh(&nf_nat_seqofs_lock);

	/* SYN adjust. If it's uninitialized, or this is after last
	 * correction, record it: we don't handle more than one
	 * adjustment in the window, but do deal with common case of a
	 * retransmit */
	if (this_way->offset_before == this_way->offset_after ||
	    before(this_way->correction_pos, seq)) {
		   this_way->correction_pos = seq;
		   this_way->offset_before = this_way->offset_after;
		   this_way->offset_after += sizediff;
	}
	spin_unlock_bh(&nf_nat_seqofs_lock);

	pr_debug("nf_nat_resize_packet: Seq_offset after: ");
	DUMP_OFFSET(this_way);
}
Пример #8
0
static void test_addNodeInTree_DuplicateNode() {
    before();
    char *path = get_absolute_path(testdir_path, "/cepa.jpg");

    VnrFile *vnrfile = vnr_file_create_new(path, "cepa.jpg", FALSE);
    GNode *node = g_node_new(vnrfile);

    GNode *tree = get_tree(SINGLE_FILE, FALSE, FALSE);
    tree = get_root_node(tree);

    add_node_in_tree(tree, node);
    char* expected = KWHT TESTDIRNAME RESET " (3 children)\n\
├─ bepa.png\n\
├─ cepa.jpg\n\
└─ epa.png\n\
";

    assert_equals("Add node in tree ─ Duplicate node: F ─ Recursive: F", expected, print_and_free_tree(tree));

    free(path);
    free_whole_tree(node);
    after();
}
Пример #9
0
static void test_addNodeInTree_TreesIn() {
    before();

    GNode *tree = get_tree(SINGLE_FILE, FALSE, FALSE);
    GNode *node = get_tree(SINGLE_FILE, FALSE, FALSE);
    tree = get_root_node(tree);
    node = get_root_node(node);

    add_node_in_tree(tree, node);
    char* expected = KWHT TESTDIRNAME RESET " (4 children)\n\
├─ bepa.png\n\
├─ cepa.jpg\n\
├─ epa.png\n\
└─┬" KWHT TESTDIRNAME RESET " (3 children)\n\
  ├─ bepa.png\n\
  ├─ cepa.jpg\n\
  └─ epa.png\n\
";

    assert_equals("Add node in tree ─ Tree in tree: F ─ Recursive: F", expected, print_and_free_tree(tree));

    after();
}
Пример #10
0
// run all tests
void run_alex_tests() {
    const int numTests = 6;
    for (int i = 1; i <= numTests; i++) {
        list* l = before();

        switch(i) {
            case 1: test_emptyList(l);
                    break;
            case 2: test_endOfList(l);
                    break;
            case 3: test_add(l);
                    break;
            case 4: test_remove(l);
                    break;
            case 5: test_list_ops(l);
                    break;
            case 6: test_copy_list_trivial(l);
                    break;
        }

        after(l);
    }
}
Пример #11
0
void Context::addWithRelativeIndent(const Context &rhs)
{
    auto addWithRelativeIndent = [this](Lines &l1, Lines l2)
    {
        for (auto &l : l2)
            l.n_indents += n_indents;
        l1 += l2;
    };

    if (before_ && rhs.before_)
        addWithRelativeIndent(before_->lines, rhs.before_->lines);
    else if (rhs.before_)
    {
        addWithRelativeIndent(before().lines, rhs.before_->lines);
    }
    addWithRelativeIndent(lines, rhs.lines);
    if (after_ && rhs.after_)
        addWithRelativeIndent(after_->lines, rhs.after_->lines);
    else if (rhs.after_)
    {
        addWithRelativeIndent(after().lines, rhs.after_->lines);
    }
}
int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
		     __be32 seq, s32 off)
{
	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	struct nf_ct_seqadj *this_way;

	if (off == 0)
		return 0;

	set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);

	spin_lock_bh(&ct->lock);
	this_way = &seqadj->seq[dir];
	if (this_way->offset_before == this_way->offset_after ||
	    before(this_way->correction_pos, ntohl(seq))) {
		this_way->correction_pos = ntohl(seq);
		this_way->offset_before	 = this_way->offset_after;
		this_way->offset_after	+= off;
	}
	spin_unlock_bh(&ct->lock);
	return 0;
}
Пример #13
0
void memory_model_sct::thread_spawn(
  symex_target_equationt &equation,
  const per_thread_mapt &per_thread_map)
{
  // thread spawn: the spawn precedes the first
  // instruction of the new thread in program order

  unsigned next_thread_id=0;
  for(eventst::const_iterator
      e_it=equation.SSA_steps.begin();
      e_it!=equation.SSA_steps.end();
      e_it++)
  {
    if(is_spawn(e_it))
    {
      per_thread_mapt::const_iterator next_thread=
        per_thread_map.find(++next_thread_id);
      if(next_thread==per_thread_map.end()) continue;

      // add a constraint for all events,
      // considering regression/cbmc-concurrency/pthread_create_tso1
      for(event_listt::const_iterator
          n_it=next_thread->second.begin();
          n_it!=next_thread->second.end();
          n_it++)
      {
        if(!(*n_it)->is_memory_barrier())
          add_constraint(
            equation,
            before(e_it, *n_it),
            "thread-spawn",
            e_it->source);
      }
    }
  }
}
Пример #14
0
static void test_addNodeInTree_TreeIsLeaf() {
    before();
    char *path = append_strings(testdir_path, "/cepa.jpg");

    VnrFile *vnrfile = vnr_file_create_new(path, "cepa.jpg", FALSE);
    GNode *node = g_node_new(vnrfile);

    GNode *tree = get_tree(SINGLE_FILE, FALSE, FALSE);
    tree = get_root_node(tree);
    GNode *bepa = assert_forward_iteration(tree, "bepa.png");

    add_node_in_tree(bepa, node);
    char* expected = KWHT TESTDIRNAME RESET " (3 children)\n\
├─ bepa.png\n\
├─ cepa.jpg\n\
└─ epa.png\n\
";

    assert_equals("Add node in tree ─ Tree is leaf ─ No change", expected, print_and_free_tree(tree));

    free(path);
    free_whole_tree(node);
    after();
}
Пример #15
0
/* Write size random bytes into file descriptor fd at the current position,
   returning the number of bytes actually written */
static uint64_t fill_file(int fd, uint64_t size)
{
	ssize_t written;
	size_t sz;
	unsigned start = 0, length;
	uint64_t remains;
	uint64_t actual_size = 0;

	init_write_buffer();
	remains = size;
	while (remains > 0) {
		length = WRITE_BUFFER_SIZE - start;
		if (remains > length)
			sz = length;
		else
			sz = (size_t) remains;
		before();
		written = write(fd, write_buffer + start, sz);
		if (written <= 0) {
			CHECK(errno == ENOSPC); /* File system full */
			errno = 0;
			after("write");
			fprintf(stderr,"\nrndrm99: write failed with ENOSPC\n");fflush(stderr);
			display_stats();
			break;
		}
		after("write");
		remains -= written;
		actual_size += written;
		if ((size_t) written == sz)
			start = 0;
		else
			start += written;
	}
	return actual_size;
}
Пример #16
0
 forceinline bool
 before(const CachedView<View>& x, const CachedView<View>& y) {
   return before(x.base(),y.base())
     || (same(x.base(),y.base()) && (x.offset() < y.offset()));
 }
static int
hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
	      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
	const struct ip_set_hash *h = set->data;
	ipset_adtfn adtfn = set->variant->adt[adt];
	u32 ip, ip_to, hosts, timeout = h->timeout;
	__be32 nip;
	int ret = 0;

	if (unlikely(!tb[IPSET_ATTR_IP] ||
		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
		return -IPSET_ERR_PROTOCOL;

	if (tb[IPSET_ATTR_LINENO])
		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);

	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
	if (ret)
		return ret;

	ip &= ip_set_hostmask(h->netmask);

	if (tb[IPSET_ATTR_TIMEOUT]) {
		if (!with_timeout(h->timeout))
			return -IPSET_ERR_TIMEOUT;
		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
	}

	if (adt == IPSET_TEST) {
		nip = htonl(ip);
		if (nip == 0)
			return -IPSET_ERR_HASH_ELEM;
		return adtfn(set, &nip, timeout, flags);
	}

	if (tb[IPSET_ATTR_IP_TO]) {
		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
		if (ret)
			return ret;
		if (ip > ip_to)
			swap(ip, ip_to);
	} else if (tb[IPSET_ATTR_CIDR]) {
		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);

		if (cidr > 32)
			return -IPSET_ERR_INVALID_CIDR;
		ip_set_mask_from_to(ip, ip_to, cidr);
	} else
		ip_to = ip;

	hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);

	if (retried)
		ip = h->next.ip;
	for (; !before(ip_to, ip); ip += hosts) {
		nip = htonl(ip);
		if (nip == 0)
			return -IPSET_ERR_HASH_ELEM;
		ret = adtfn(set, &nip, timeout, flags);

		if (ret && !ip_set_eexist(ret, flags))
			return ret;
		else
			ret = 0;
	}
	return ret;
}
Пример #18
0
/*
 * range - supply cvec for a range, including legality check
 */
static struct cvec *
range(struct vars * v,			/* context */
	  celt a,					/* range start */
	  celt b,					/* range end, might equal a */
	  int cases)				/* case-independent? */
{
	int			nchrs;
	struct cvec *cv;
	celt		c,
				cc;

	if (a != b && !before(a, b))
	{
		ERR(REG_ERANGE);
		return NULL;
	}

	if (!cases)
	{							/* easy version */
		cv = getcvec(v, 0, 1);
		NOERRN();
		addrange(cv, a, b);
		return cv;
	}

	/*
	* When case-independent, it's hard to decide when cvec ranges are usable,
	* so for now at least, we won't try.  We use a range for the originally
	* specified chrs and then add on any case-equivalents that are outside
	* that range as individual chrs.
	*
	* To ensure sane behavior if someone specifies a very large range, limit
	* the allocation size to 100000 chrs (arbitrary) and check for overrun
	* inside the loop below.
	*/

	nchrs = b - a + 1;
    
	if (nchrs <= 0 || nchrs > 100000)
		nchrs = 100000;

	cv = getcvec(v, nchrs, 1);
	NOERRN();
	addrange(cv, a, b);

	for (c = a; c <= b; c++)
	{
		cc = pg_wc_tolower((chr) c);
		if (cc !=c && (before(cc, a) || before(b, cc)))
		{
			if (cv->nchrs >= cv->chrspace)
			{
				ERR(REG_ETOOBIG);
				return NULL;
			}
			addchr(cv, cc);
		}
		cc = pg_wc_toupper((chr) c);
		if (cc != c && (before(cc, a) || before(b, cc)))
		{
			if (cv->nchrs >= cv->chrspace)
			{
				ERR(REG_ETOOBIG);
				return NULL;
			}
			addchr(cv, cc);
		}
	}

	return cv;
}
Пример #19
0
// -------------------------
int _tmain(int argc, _TCHAR* argv[])
{


	// decl a default time
	cTime a;

	// a.mHours == 0

	// decl a time set to 1:15:30 (and :0 ms)
	cTime b( 1, 15, 30 );

	SYSTEMTIME st;
	//GetSystemTime(&st);
	GetLocalTime(&st);
		// regular constructor
	cTime now(st);
	
	// decl a time set to the value of b
	cTime c(b); // const

	// copy c to d
		// equality operator
	cTime d = c;	// half as efficient as cTime d( c );

	a.ToString();
	b.ToString();
	c.ToString();
	d.ToString();
	now.ToString();

	if(c == b)
	{
		cout << "c == b" << endl;
	}
	else
	{
		cout << "c != b" << endl;
	}

	cTime stopTime(0, 0, 30);
	cTime clock; //0, 0, 0
	cTime frameTime(0, 0, 1); //1 frame per second
	GetLocalTime(&st);
	cTime before(st);

	while(clock < stopTime)
	{
		GetLocalTime(&st);
		cTime now(st);
		cTime elapsed = now - before;
		if(elapsed >= frameTime)
		{
			clock += (elapsed.CalcSum());
			clock.ToString();
			before = now;
		}
	}

	//::OutputDebugString("Hello World\n"); //great to use later on for debugging

	cout << "Time is up!" << endl;

	return 0;
}
Пример #20
0
void AbstractTwoLevelAgreement::overLapMainFinished(int i,int j,const SelectionList & tagNames, const SelectionList & outputNames,int &numNames) {
    bool underComputation=(&numNames==&underNumNames);
    assert(underComputation || (i<0 && j<0 )); //if in max-boundary, i and j have no significance
    QSet<int> visitedTags;
    int allCommonCount;
    int countCommon=commonNames(tagNames,outputNames,visitedTags,allCommonCount);
    int countCorrect=tagNames.size();
    int countDetected=outputNames.size();
    assert (countCommon<=countDetected);
    if (countCorrect>0) {
        numNames+=countCorrect;
        double	recall=(double)countCommon/countCorrect * countCorrect,
                precision=(double)countCommon/countDetected *countCorrect;
        if (countDetected==0)
            precision=0;
        if (underComputation) {
            underNameRecallList.append(recall);
            underNamePrecisionList.append(precision);
        } else {
            nameRecallList.append(recall);
            namePrecisionList.append(precision);
        }
        int k=0,h=0;
        QList<int> common_k,common_h;
        SelectionList tagWords, outputWords;
        while (k<tagNames.size() && h<outputNames.size()) {
            int start1=tagNames[k].first,end1=tagNames[k].second,
                start2=outputNames[h].first,end2=outputNames[h].second;
            if (overLaps(start1,end1,start2,end2) && start1!=end2) {
                bool foundK=common_k.contains(k), foundH=common_h.contains(h);
                if (underComputation)
                    startNamesOverLap(i,j,k,h,countCommon);
                if (!foundK /*&& !foundJ*/) {//so that merged parts will not be double counted
                    common_k.append(k);
                    tagWords.append(tagNames[k]);
                    if (foundH) { //new correctnode that matches detected
                        if (underComputation)
                            anotherTagOverLapPreviousOutputName(i,j,k,h);
                    }
                }
                if (!foundH) {//common_i and common_j now are not same size, bc recall and precision need different treatment for overlap
                    common_h.append(h);
                    outputWords.append(outputNames[h]);
                    if (foundK) { //new detectednode that matches correct
                        if (underComputation)
                            anotherOutputOverLapPreviousTagName(i,j,k,h);
                    }
                }
                if (!foundK && !foundH) {
                    if (underComputation)
                        firstNameOverLap(i,j,k,h);
                }
                //[underboundary computations
                SelectionList singleTagWords, singleOutputWords;
                singleTagWords.append(tagNames[k]);
                singleOutputWords.append(outputNames[h]);
                overLapNamesFinished(singleTagWords,singleOutputWords,underNumWords);
                //]
                int process=0;
                if (end1<=end2 ) {
                    k++;
                    process++;
                }
                if (end2<=end1) {
                    h++;
                    process++;
                }
                if (process==2) {
                    //[max-boundary computations
                    overLapNamesFinished(tagWords,outputWords,numWords);
                    //]
                    tagWords.clear();
                    outputWords.clear();
                }
            } else if (before(start1,end1,start2,end2)) {
                if (underComputation)
                    beforeMovingToNextTagName(i,j,k,h);
                //[max-boundary computations
                overLapNamesFinished(tagWords,outputWords,numWords);
                //]
                tagWords.clear();
                outputWords.clear();
                k++;
            } else if (after(start1,end1,start2,end2) ) {
                if (underComputation)
                    beforeMovingToNextOutputName(i,j,k,h);
                //[max-boundary computations
                overLapNamesFinished(tagWords,outputWords,numWords);
                //]
                tagWords.clear();
                outputWords.clear();
                h++;
            }
        }
        if (tagWords.size()>0 || outputWords.size()>0) {
            //[max-boundary computations
            overLapNamesFinished(tagWords,outputWords,numWords);
            //]
            tagWords.clear();
            outputWords.clear();
        }
    } else {
        nameRecallList.append(0);
        namePrecisionList.append(0);
    }
    if (underComputation) { //under computation only
        if (hadithParameters.detailed_statistics) {
            theSarf->displayed_error	<</*text->mid(start1,end1-start1+1)*/i<<"\t"
                <</*text->mid(start2,end2-start2+1)*/j<<"\t"
                <<countCommon<<"/"<<countCorrect<<"\t"<<allCommonCount<<"/"<<countDetected<<"\n";
        }
    }
}
Пример #21
0
int AbstractTwoLevelAgreement::calculateStatisticsHelper() {

    common_i.clear();
    common_j.clear();
    nameRecallList.clear();
    namePrecisionList.clear();
    boundaryRecallList.clear();
    boundaryPrecisionList.clear();
    underNameRecallList.clear();
    underNamePrecisionList.clear();
    underBoundaryRecallList.clear();
    underBoundaryPrecisionList.clear();

    qSort(tags.begin(),tags.end());
    for (int i=0;i<tags.size();i++) {
        tags[i].setText(text);
        AbstractGraph * g=tags[i].getGraph();
        if (g!=NULL)
            g->fillTextPointers(text);

    }
    if (annotatedGraph!=NULL)
        annotatedGraph->fillTextPointers(text);

    initializeAuxiliaryCountersLists();
    currentTagLists.clear();
    currentOutputLists.clear();
    numNames=0;
    underNumNames=0;
    numWords=0;
    underNumWords=0;

    int i=0,j=0;
    SelectionList tagNamesOverLap, outputNamesOverLap;
    while (i<tags.size() && j<outputList.size()) {
        int start1=tags[i].getMainStart(),end1=tags[i].getMainEnd(),
            start2=outputList[j].getMainStart(),end2=outputList[j].getMainEnd();
        if (overLaps(start1,end1,start2,end2) && start1!=end2) {
            const SelectionList & tagNames=tags[i].getNamesList(),
                  & outputNames=outputList[j].getNamesList();
            bool foundI=common_i.contains(i), foundJ=common_j.contains(j);
            if (!foundI /*&& !foundJ*/) {//so that merged parts will not be double counted
                common_i.append(i);
                tagNamesOverLap.append(tagNames);
            } else {
                currentOutputLists.append(j);
            }
            if (!foundJ) {//common_i and common_j now are not same size, bc recall and precision need different treatment for overlap
                common_j.append(j);
                outputNamesOverLap.append(outputNames);
            } else {
                currentTagLists.append(i);
            }
            //[underboundary computations
            overLapMainFinished(i,j,tagNames,outputNames,underNumNames);
            //]

            int progress=0;
            if (end1<=end2 ) {
                i++;
                progress++;
            }
            if (end2<=end1) {
                j++;
                progress++;
            }
            if (progress==2) {
                //[max-boundary computations
                overLapMainFinished(-1,-1,tagNamesOverLap,outputNamesOverLap,numNames);
                //]
                tagNamesOverLap.clear();
                outputNamesOverLap.clear();
            }
        } else if (before(start1,end1,start2,end2)) {
            if (hadithParameters.detailed_statistics) {
                theSarf->displayed_error	<</*text->mid(start1,end1-start1+1)*/i<<"\t"
                    <<"-----\n";
            }
            //[max-boundary computations
            overLapMainFinished(-1,-1,tagNamesOverLap,outputNamesOverLap,numNames);
            //]
            tagNamesOverLap.clear();
            outputNamesOverLap.clear();
            beforeMovingToNextTag(i,j);
            i++;
        } else if (after(start1,end1,start2,end2) ) {
            if (hadithParameters.detailed_statistics) {
                theSarf->displayed_error	<<"-----\t"
                    <</*text->mid(start2,end2-start2+1)*/j<<"\n";
            }
            //[max-boundary computations
            overLapMainFinished(-1,-1,tagNamesOverLap,outputNamesOverLap,numNames);
            //]
            tagNamesOverLap.clear();
            outputNamesOverLap.clear();
            beforeMovingToNextOutput(i,j);
            j++;
        }
    }
    if (tagNamesOverLap.size()>0 || outputNamesOverLap.size()>0) {
        //[max-boundary computations
        overLapMainFinished(-1,-1,tagNamesOverLap,outputNamesOverLap,numNames);
        //]
        tagNamesOverLap.clear();
        outputNamesOverLap.clear();
    }
    while (i<tags.size()) {
        if (hadithParameters.detailed_statistics) {
            //int start1=tags[i].getMainStart(),end1=tags[i].getMainEnd();
            theSarf->displayed_error <</*text->mid(start1,end1-start1+1)*/i<<"\t"
                <<"-----\n";
        }
        beforeMovingToNextTag(i,j);
        i++;
    }
    while (j<outputList.size()) {
        if (hadithParameters.detailed_statistics) {
            //int start2=outputList[j].getMainStart(),end2=outputList[j].getMainEnd();
            theSarf->displayed_error <<"-----\t"
                <</*text->mid(start2,end2-start2+1)*/j<<"\n";
            beforeMovingToNextOutput(i,j);
        }
        j++;
    }

    commonCount=common_i.size();
    allCommonCount=common_j.size();
    correctTagsCount=tags.size();
    generatedTagsCount=outputList.size();
    segmentationRecall=(double)commonCount/tags.size();
    segmentationPrecision=(double)allCommonCount/outputList.size();
    underSegmentationRatio=(double)commonCount/allCommonCount;
    nameRecall=sum(nameRecallList)/numNames;
    namePrecision=sum(namePrecisionList)/numNames;
    boundaryRecall=sum(boundaryRecallList)/numWords;
    boundaryPrecision=sum(boundaryPrecisionList)/numWords;
    underNameRecall=sum(underNameRecallList)/underNumNames;
    underNamePrecision=sum(underNamePrecisionList)/underNumNames;
    underBoundaryRecall=sum(underBoundaryRecallList)/underNumWords;
    underBoundaryPrecision=sum(underBoundaryPrecisionList)/underNumWords;

    return 0;
}
Пример #22
0
void CSSSelector::extractPseudoType() const
{
    if (m_match != PseudoClass && m_match != PseudoElement)
        return;

    AtomicString active("active");
    AtomicString after("after");
    AtomicString anyLink("-webkit-any-link");
    AtomicString autofill("-webkit-autofill");
    AtomicString before("before");
    AtomicString checked("checked");
    AtomicString fileUploadButton("-webkit-file-upload-button");
    AtomicString disabled("disabled");
    AtomicString drag("-webkit-drag");
    AtomicString dragAlias("-khtml-drag"); // was documented with this name in Apple documentation, so keep an alias
    AtomicString empty("empty");
    AtomicString enabled("enabled");
    AtomicString firstChild("first-child");
    AtomicString firstLetter("first-letter");
    AtomicString firstLine("first-line");
    AtomicString firstOfType("first-of-type");
    AtomicString nthChild("nth-child(");
    AtomicString nthOfType("nth-of-type(");
    AtomicString nthLastChild("nth-last-child(");
    AtomicString nthLastOfType("nth-last-of-type(");
    AtomicString focus("focus");
    AtomicString hover("hover");
    AtomicString indeterminate("indeterminate");
    AtomicString lastChild("last-child");
    AtomicString lastOfType("last-of-type");
    AtomicString link("link");
    AtomicString lang("lang(");
    AtomicString mediaControlsPanel("-webkit-media-controls-panel");
    AtomicString mediaControlsMuteButton("-webkit-media-controls-mute-button");
    AtomicString mediaControlsPlayButton("-webkit-media-controls-play-button");
    AtomicString mediaControlsTimeDisplay("-webkit-media-controls-time-display");
    AtomicString mediaControlsTimeline("-webkit-media-controls-timeline");
    AtomicString mediaControlsSeekBackButton("-webkit-media-controls-seek-back-button");
    AtomicString mediaControlsSeekForwardButton("-webkit-media-controls-seek-forward-button");
    AtomicString mediaControlsFullscreenButton("-webkit-media-controls-fullscreen-button");
    AtomicString notStr("not(");
    AtomicString onlyChild("only-child");
    AtomicString onlyOfType("only-of-type");
    AtomicString root("root");
    AtomicString searchCancelButton("-webkit-search-cancel-button");
    AtomicString searchDecoration("-webkit-search-decoration");
    AtomicString searchResultsDecoration("-webkit-search-results-decoration");
    AtomicString searchResultsButton("-webkit-search-results-button");
    AtomicString selection("selection");
    AtomicString sliderThumb("-webkit-slider-thumb");
    AtomicString target("target");
    AtomicString visited("visited");

    bool element = false; // pseudo-element
    bool compat = false; // single colon compatbility mode

    m_pseudoType = PseudoUnknown;
    if (m_value == active)
        m_pseudoType = PseudoActive;
    else if (m_value == after) {
        m_pseudoType = PseudoAfter;
        element = true;
        compat = true;
    } else if (m_value == anyLink)
        m_pseudoType = PseudoAnyLink;
    else if (m_value == autofill)
        m_pseudoType = PseudoAutofill;
    else if (m_value == before) {
        m_pseudoType = PseudoBefore;
        element = true;
        compat = true;
    } else if (m_value == checked)
        m_pseudoType = PseudoChecked;
    else if (m_value == fileUploadButton) {
        m_pseudoType = PseudoFileUploadButton;
        element = true;
    } else if (m_value == disabled)
        m_pseudoType = PseudoDisabled;
    else if (m_value == drag || m_value == dragAlias)
        m_pseudoType = PseudoDrag;
    else if (m_value == enabled)
        m_pseudoType = PseudoEnabled;
    else if (m_value == empty)
        m_pseudoType = PseudoEmpty;
    else if (m_value == firstChild)
        m_pseudoType = PseudoFirstChild;
    else if (m_value == lastChild)
        m_pseudoType = PseudoLastChild;
    else if (m_value == lastOfType)
        m_pseudoType = PseudoLastOfType;
    else if (m_value == onlyChild)
        m_pseudoType = PseudoOnlyChild;
    else if (m_value == onlyOfType)
        m_pseudoType = PseudoOnlyOfType;
    else if (m_value == firstLetter) {
        m_pseudoType = PseudoFirstLetter;
        element = true;
        compat = true;
    } else if (m_value == firstLine) {
        m_pseudoType = PseudoFirstLine;
        element = true;
        compat = true;
    } else if (m_value == firstOfType)
        m_pseudoType = PseudoFirstOfType;
    else if (m_value == focus)
        m_pseudoType = PseudoFocus;
    else if (m_value == hover)
        m_pseudoType = PseudoHover;
    else if (m_value == indeterminate)
        m_pseudoType = PseudoIndeterminate;
    else if (m_value == link)
        m_pseudoType = PseudoLink;
    else if (m_value == lang)
        m_pseudoType = PseudoLang;
    else if (m_value == mediaControlsPanel) {
        m_pseudoType = PseudoMediaControlsPanel;
        element = true;
    } else if (m_value == mediaControlsMuteButton) {
        m_pseudoType = PseudoMediaControlsMuteButton;
        element = true;
    } else if (m_value == mediaControlsPlayButton) {
        m_pseudoType = PseudoMediaControlsPlayButton;
        element = true;
    } else if (m_value == mediaControlsTimeDisplay) {
        m_pseudoType = PseudoMediaControlsTimeDisplay;
        element = true;
    } else if (m_value == mediaControlsTimeline) {
        m_pseudoType = PseudoMediaControlsTimeline;
        element = true;
    } else if (m_value == mediaControlsSeekBackButton) {
        m_pseudoType = PseudoMediaControlsSeekBackButton;
        element = true;
    } else if (m_value == mediaControlsSeekForwardButton) {
        m_pseudoType = PseudoMediaControlsSeekForwardButton;
        element = true;
    } else if (m_value == mediaControlsFullscreenButton) {
        m_pseudoType = PseudoMediaControlsFullscreenButton;
        element = true;
    } else if (m_value == notStr)
        m_pseudoType = PseudoNot;
    else if (m_value == nthChild)
        m_pseudoType = PseudoNthChild;
    else if (m_value == nthOfType)
        m_pseudoType = PseudoNthOfType;
    else if (m_value == nthLastChild)
        m_pseudoType = PseudoNthLastChild;
    else if (m_value == nthLastOfType)
        m_pseudoType = PseudoNthLastOfType;
    else if (m_value == root)
        m_pseudoType = PseudoRoot;
    else if (m_value == searchCancelButton) {
        m_pseudoType = PseudoSearchCancelButton;
        element = true;
    } else if (m_value == searchDecoration) {
        m_pseudoType = PseudoSearchDecoration;
        element = true;
    } else if (m_value == searchResultsDecoration) {
        m_pseudoType = PseudoSearchResultsDecoration;
        element = true;
    } else if (m_value == searchResultsButton) {
        m_pseudoType = PseudoSearchResultsButton;
        element = true;
    }  else if (m_value == selection) {
        m_pseudoType = PseudoSelection;
        element = true;
    } else if (m_value == sliderThumb) {
        m_pseudoType = PseudoSliderThumb;
        element = true;
    } else if (m_value == target)
        m_pseudoType = PseudoTarget;
    else if (m_value == visited)
        m_pseudoType = PseudoVisited;

    if (m_match == PseudoClass && element) {
        if (!compat)
            m_pseudoType = PseudoUnknown;
        else
            m_match = PseudoElement;
    } else if (m_match == PseudoElement && !element)
        m_pseudoType = PseudoUnknown;
}
Пример #23
0
static int
bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
	       enum ipset_adt adt, u32 *lineno, u32 flags)
{
	struct bitmap_ip *map = set->data;
	ipset_adtfn adtfn = set->variant->adt[adt];
	u32 timeout = map->timeout;
	u32 ip, ip_to, id;
	int ret = 0;

	if (unlikely(!tb[IPSET_ATTR_IP] ||
		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
		return -IPSET_ERR_PROTOCOL;

	if (tb[IPSET_ATTR_LINENO])
		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);

	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
	if (ret)
		return ret;

	if (ip < map->first_ip || ip > map->last_ip)
		return -IPSET_ERR_BITMAP_RANGE;

	if (tb[IPSET_ATTR_TIMEOUT]) {
		if (!with_timeout(map->timeout))
			return -IPSET_ERR_TIMEOUT;
		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
	}

	if (adt == IPSET_TEST) {
		id = ip_to_id(map, ip);
		return adtfn(set, &id, timeout);
	}

	if (tb[IPSET_ATTR_IP_TO]) {
		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
		if (ret)
			return ret;
		if (ip > ip_to) {
			swap(ip, ip_to);
			if (ip < map->first_ip)
				return -IPSET_ERR_BITMAP_RANGE;
		}
	} else if (tb[IPSET_ATTR_CIDR]) {
		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);

		if (cidr > 32)
			return -IPSET_ERR_INVALID_CIDR;
		ip &= ip_set_hostmask(cidr);
		ip_to = ip | ~ip_set_hostmask(cidr);
	} else
		ip_to = ip;

	if (ip_to > map->last_ip)
		return -IPSET_ERR_BITMAP_RANGE;

	for (; !before(ip_to, ip); ip += map->hosts) {
		id = ip_to_id(map, ip);
		ret = adtfn(set, &id, timeout);;

		if (ret && !ip_set_eexist(ret, flags))
			return ret;
		else
			ret = 0;
	}
	return ret;
}
static int tcp_packet(struct nf_conn *ct,
		      const struct sk_buff *skb,
		      unsigned int dataoff,
		      enum ip_conntrack_info ctinfo,
		      u_int8_t pf,
		      unsigned int hooknum,
		      unsigned int *timeouts)
{
	struct net *net = nf_ct_net(ct);
	struct nf_conntrack_tuple *tuple;
	enum tcp_conntrack new_state, old_state;
	enum ip_conntrack_dir dir;
	const struct tcphdr *th;
	struct tcphdr _tcph;
	unsigned long timeout;
	unsigned int index;

	th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
	BUG_ON(th == NULL);

	spin_lock_bh(&ct->lock);
	old_state = ct->proto.tcp.state;
	dir = CTINFO2DIR(ctinfo);
	index = get_conntrack_index(th);
	new_state = tcp_conntracks[dir][index][old_state];
	tuple = &ct->tuplehash[dir].tuple;

	switch (new_state) {
	case TCP_CONNTRACK_SYN_SENT:
		if (old_state < TCP_CONNTRACK_TIME_WAIT)
			break;
		if (((ct->proto.tcp.seen[dir].flags
		      | ct->proto.tcp.seen[!dir].flags)
		     & IP_CT_TCP_FLAG_CLOSE_INIT)
		    || (ct->proto.tcp.last_dir == dir
		        && ct->proto.tcp.last_index == TCP_RST_SET)) {
			spin_unlock_bh(&ct->lock);

			if (nf_ct_kill(ct))
				return -NF_REPEAT;
			return NF_DROP;
		}
		
	case TCP_CONNTRACK_IGNORE:
		if (index == TCP_SYNACK_SET
		    && ct->proto.tcp.last_index == TCP_SYN_SET
		    && ct->proto.tcp.last_dir != dir
		    && ntohl(th->ack_seq) == ct->proto.tcp.last_end) {
			old_state = TCP_CONNTRACK_SYN_SENT;
			new_state = TCP_CONNTRACK_SYN_RECV;
			ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_end =
				ct->proto.tcp.last_end;
			ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_maxend =
				ct->proto.tcp.last_end;
			ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_maxwin =
				ct->proto.tcp.last_win == 0 ?
					1 : ct->proto.tcp.last_win;
			ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale =
				ct->proto.tcp.last_wscale;
			ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags =
				ct->proto.tcp.last_flags;
			memset(&ct->proto.tcp.seen[dir], 0,
			       sizeof(struct ip_ct_tcp_state));
			break;
		}
		ct->proto.tcp.last_index = index;
		ct->proto.tcp.last_dir = dir;
		ct->proto.tcp.last_seq = ntohl(th->seq);
		ct->proto.tcp.last_end =
		    segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th);
		ct->proto.tcp.last_win = ntohs(th->window);

		if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) {
			struct ip_ct_tcp_state seen = {};

			ct->proto.tcp.last_flags =
			ct->proto.tcp.last_wscale = 0;
			tcp_options(skb, dataoff, th, &seen);
			if (seen.flags & IP_CT_TCP_FLAG_WINDOW_SCALE) {
				ct->proto.tcp.last_flags |=
					IP_CT_TCP_FLAG_WINDOW_SCALE;
				ct->proto.tcp.last_wscale = seen.td_scale;
			}
			if (seen.flags & IP_CT_TCP_FLAG_SACK_PERM) {
				ct->proto.tcp.last_flags |=
					IP_CT_TCP_FLAG_SACK_PERM;
			}
		}
		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_TCP))
			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
				  "nf_ct_tcp: invalid packet ignored ");
		return NF_ACCEPT;
	case TCP_CONNTRACK_MAX:
		
		pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
			 dir, get_conntrack_index(th), old_state);
		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_TCP))
			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
				  "nf_ct_tcp: invalid state ");
		return -NF_ACCEPT;
	case TCP_CONNTRACK_CLOSE:
		if (index == TCP_RST_SET
		    && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET)
		    && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) {
			
			spin_unlock_bh(&ct->lock);
			if (LOG_INVALID(net, IPPROTO_TCP))
				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
					  "nf_ct_tcp: invalid RST ");
			return -NF_ACCEPT;
		}
		if (index == TCP_RST_SET
		    && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status)
			 && ct->proto.tcp.last_index == TCP_SYN_SET)
			|| (!test_bit(IPS_ASSURED_BIT, &ct->status)
			    && ct->proto.tcp.last_index == TCP_ACK_SET))
		    && ntohl(th->ack_seq) == ct->proto.tcp.last_end) {
			goto in_window;
		}
		
	default:
		
		break;
	}

	if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
			   skb, dataoff, th, pf)) {
		spin_unlock_bh(&ct->lock);
		return -NF_ACCEPT;
	}
     in_window:
	
	ct->proto.tcp.last_index = index;
	ct->proto.tcp.last_dir = dir;

	pr_debug("tcp_conntracks: ");
	nf_ct_dump_tuple(tuple);
	pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
		 (th->syn ? 1 : 0), (th->ack ? 1 : 0),
		 (th->fin ? 1 : 0), (th->rst ? 1 : 0),
		 old_state, new_state);

	ct->proto.tcp.state = new_state;
	if (old_state != new_state
	    && new_state == TCP_CONNTRACK_FIN_WAIT)
		ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;

	if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans &&
	    timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
		timeout = timeouts[TCP_CONNTRACK_RETRANS];
	else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
		 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
		 timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
		timeout = timeouts[TCP_CONNTRACK_UNACK];
	else
		timeout = timeouts[new_state];
	spin_unlock_bh(&ct->lock);

	if (new_state != old_state)
		nf_conntrack_event_cache(IPCT_PROTOINFO, ct);

	if (!test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
		if (th->rst) {
			nf_ct_kill_acct(ct, ctinfo, skb);
			return NF_ACCEPT;
		}
	} else if (!test_bit(IPS_ASSURED_BIT, &ct->status)
		   && (old_state == TCP_CONNTRACK_SYN_RECV
		       || old_state == TCP_CONNTRACK_ESTABLISHED)
		   && new_state == TCP_CONNTRACK_ESTABLISHED) {
		set_bit(IPS_ASSURED_BIT, &ct->status);
		nf_conntrack_event_cache(IPCT_ASSURED, ct);
	}
	nf_ct_refresh_acct(ct, ctinfo, skb, timeout);

	return NF_ACCEPT;
}
static bool tcp_in_window(const struct nf_conn *ct,
			  struct ip_ct_tcp *state,
			  enum ip_conntrack_dir dir,
			  unsigned int index,
			  const struct sk_buff *skb,
			  unsigned int dataoff,
			  const struct tcphdr *tcph,
			  u_int8_t pf)
{
	struct net *net = nf_ct_net(ct);
	struct ip_ct_tcp_state *sender = &state->seen[dir];
	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
	const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
	__u32 seq, ack, sack, end, win, swin;
	s16 receiver_offset;
	bool res;

	seq = ntohl(tcph->seq);
	ack = sack = ntohl(tcph->ack_seq);
	win = ntohs(tcph->window);
	end = segment_seq_plus_len(seq, skb->len, dataoff, tcph);

	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
		tcp_sack(skb, dataoff, tcph, &sack);

	
	receiver_offset = NAT_OFFSET(pf, ct, !dir, ack - 1);
	ack -= receiver_offset;
	sack -= receiver_offset;

	pr_debug("tcp_in_window: START\n");
	pr_debug("tcp_in_window: ");
	nf_ct_dump_tuple(tuple);
	pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
		 seq, ack, receiver_offset, sack, receiver_offset, win, end);
	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
		 sender->td_end, sender->td_maxend, sender->td_maxwin,
		 sender->td_scale,
		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
		 receiver->td_scale);

	if (sender->td_maxwin == 0) {
		if (tcph->syn) {
			sender->td_end =
			sender->td_maxend = end;
			sender->td_maxwin = (win == 0 ? 1 : win);

			tcp_options(skb, dataoff, tcph, sender);
			if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
			      && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
				sender->td_scale =
				receiver->td_scale = 0;
			if (!tcph->ack)
				
				return true;
		} else {
			sender->td_end = end;
			swin = win << sender->td_scale;
			sender->td_maxwin = (swin == 0 ? 1 : swin);
			sender->td_maxend = end + sender->td_maxwin;
			if (receiver->td_maxwin == 0)
				receiver->td_end = receiver->td_maxend = sack;
		}
	} else if (((state->state == TCP_CONNTRACK_SYN_SENT
		     && dir == IP_CT_DIR_ORIGINAL)
		   || (state->state == TCP_CONNTRACK_SYN_RECV
		     && dir == IP_CT_DIR_REPLY))
		   && after(end, sender->td_end)) {
		sender->td_end =
		sender->td_maxend = end;
		sender->td_maxwin = (win == 0 ? 1 : win);

		tcp_options(skb, dataoff, tcph, sender);
	}

	if (!(tcph->ack)) {
		ack = sack = receiver->td_end;
	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) ==
		    (TCP_FLAG_ACK|TCP_FLAG_RST))
		   && (ack == 0)) {
		ack = sack = receiver->td_end;
	}

	if (seq == end
	    && (!tcph->rst
		|| (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
		seq = end = sender->td_end;

	pr_debug("tcp_in_window: ");
	nf_ct_dump_tuple(tuple);
	pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
		 seq, ack, receiver_offset, sack, receiver_offset, win, end);
	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
		 sender->td_end, sender->td_maxend, sender->td_maxwin,
		 sender->td_scale,
		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
		 receiver->td_scale);

	pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
		 before(seq, sender->td_maxend + 1),
		 after(end, sender->td_end - receiver->td_maxwin - 1),
		 before(sack, receiver->td_end + 1),
		 after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1));

	if (before(seq, sender->td_maxend + 1) &&
	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
	    before(sack, receiver->td_end + 1) &&
	    after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) {
		if (!tcph->syn)
			win <<= sender->td_scale;

		swin = win + (sack - ack);
		if (sender->td_maxwin < swin)
			sender->td_maxwin = swin;
		if (after(end, sender->td_end)) {
			sender->td_end = end;
			sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
		}
		if (tcph->ack) {
			if (!(sender->flags & IP_CT_TCP_FLAG_MAXACK_SET)) {
				sender->td_maxack = ack;
				sender->flags |= IP_CT_TCP_FLAG_MAXACK_SET;
			} else if (after(ack, sender->td_maxack))
				sender->td_maxack = ack;
		}

		if (receiver->td_maxwin != 0 && after(end, sender->td_maxend))
			receiver->td_maxwin += end - sender->td_maxend;
		if (after(sack + win, receiver->td_maxend - 1)) {
			receiver->td_maxend = sack + win;
			if (win == 0)
				receiver->td_maxend++;
		}
		if (ack == receiver->td_end)
			receiver->flags &= ~IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;

		if (index == TCP_ACK_SET) {
			if (state->last_dir == dir
			    && state->last_seq == seq
			    && state->last_ack == ack
			    && state->last_end == end
			    && state->last_win == win)
				state->retrans++;
			else {
				state->last_dir = dir;
				state->last_seq = seq;
				state->last_ack = ack;
				state->last_end = end;
				state->last_win = win;
				state->retrans = 0;
			}
		}
		res = true;
	} else {
		res = false;
		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
		    nf_ct_tcp_be_liberal)
			res = true;
		if (!res && LOG_INVALID(net, IPPROTO_TCP))
			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
			"nf_ct_tcp: %s ",
			before(seq, sender->td_maxend + 1) ?
			after(end, sender->td_end - receiver->td_maxwin - 1) ?
			before(sack, receiver->td_end + 1) ?
			after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG"
			: "ACK is under the lower bound (possible overly delayed ACK)"
			: "ACK is over the upper bound (ACKed data not seen yet)"
			: "SEQ is under the lower bound (already ACKed data retransmitted)"
			: "SEQ is over the upper bound (over the window of the receiver)");
	}

	pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
		 "receiver end=%u maxend=%u maxwin=%u\n",
		 res, sender->td_end, sender->td_maxend, sender->td_maxwin,
		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin);

	return res;
}
Пример #26
0
void process_tcp(u_char * data, int skblen)
{
//   printf("into process_tcp\n");
  struct ip *this_iphdr = (struct ip *)data;
  struct tcphdr *this_tcphdr = (struct tcphdr *)(data + 4 * this_iphdr->ip_hl);
  int datalen, iplen;
  int from_client = 1;
  unsigned int tmp_ts;
  struct tcp_stream *a_tcp;
  struct half_stream *snd, *rcv;

  ugly_iphdr = this_iphdr;
  iplen = ntohs(this_iphdr->ip_len);
  if ((unsigned)iplen < 4 * this_iphdr->ip_hl + sizeof(struct tcphdr)) {
    nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
		       this_tcphdr);
    return;
  } // ktos sie bawi
  
  datalen = iplen - 4 * this_iphdr->ip_hl - 4 * this_tcphdr->th_off;
  
  if (datalen < 0) {
    nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
		       this_tcphdr);
    return;
  } // ktos sie bawi

  if ((this_iphdr->ip_src.s_addr | this_iphdr->ip_dst.s_addr) == 0) {
    nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
		       this_tcphdr);
    return;
  }
  /*
  if (!(this_tcphdr->th_flags & TH_ACK))
    detect_scan(this_iphdr);
  */  
if (!nids_params.n_tcp_streams) return;
  if (my_tcp_check(this_tcphdr, iplen - 4 * this_iphdr->ip_hl,
		   this_iphdr->ip_src.s_addr, this_iphdr->ip_dst.s_addr)) {
    nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr,
		       this_tcphdr);
    //return;
  }
#if 0
  check_flags(this_iphdr, this_tcphdr);
//ECN
#endif
  if (!(a_tcp = find_stream(this_tcphdr, this_iphdr, &from_client))) {
    if ((this_tcphdr->th_flags & TH_SYN) &&
	!(this_tcphdr->th_flags & TH_ACK) &&
	!(this_tcphdr->th_flags & TH_RST))
      add_new_tcp(this_tcphdr, this_iphdr);
//     printf("add new\n");
    return;
  }
//   printf("tcp exist\n");

  if (from_client) {
    snd = &a_tcp->client;
    rcv = &a_tcp->server;
  }
  else {
    rcv = &a_tcp->client;
    snd = &a_tcp->server;
  }
  if ((this_tcphdr->th_flags & TH_SYN)) {
    if (from_client || a_tcp->client.state != TCP_SYN_SENT ||
      a_tcp->server.state != TCP_CLOSE || !(this_tcphdr->th_flags & TH_ACK))
      return;
    if (a_tcp->client.seq != ntohl(this_tcphdr->th_ack))
      return;
    a_tcp->server.state = TCP_SYN_RECV;
    a_tcp->server.seq = ntohl(this_tcphdr->th_seq) + 1;
    a_tcp->server.first_data_seq = a_tcp->server.seq;
    a_tcp->server.ack_seq = ntohl(this_tcphdr->th_ack);
    a_tcp->server.window = ntohs(this_tcphdr->th_win);
    if (a_tcp->client.ts_on) {
    	a_tcp->server.ts_on = get_ts(this_tcphdr, &a_tcp->server.curr_ts);
	if (!a_tcp->server.ts_on)
		a_tcp->client.ts_on = 0;
    } else a_tcp->server.ts_on = 0;	
    if (a_tcp->client.wscale_on) {
    	a_tcp->server.wscale_on = get_wscale(this_tcphdr, &a_tcp->server.wscale);
	if (!a_tcp->server.wscale_on) {
		a_tcp->client.wscale_on = 0;
		a_tcp->client.wscale  = 1;
		a_tcp->server.wscale = 1;
	}	
    } else {
    	a_tcp->server.wscale_on = 0;	
    	a_tcp->server.wscale = 1;
    }	
    return;
  }
  if (
  	! (  !datalen && ntohl(this_tcphdr->th_seq) == rcv->ack_seq  )
  	&&
  	( !before(ntohl(this_tcphdr->th_seq), rcv->ack_seq + rcv->window*rcv->wscale) ||
          before(ntohl(this_tcphdr->th_seq) + datalen, rcv->ack_seq)  
        )
     )     
     return;

  if ((this_tcphdr->th_flags & TH_RST)) {
    if (a_tcp->nids_state == NIDS_DATA) {
      struct lurker_node *i;
      
      a_tcp->nids_state = NIDS_RESET;
      for (i = a_tcp->listeners; i; i = i->next)
	(i->item) (a_tcp, &i->data);
    }
    free_tcp(a_tcp);
    return;
  }

  /* PAWS check */
  if (rcv->ts_on && get_ts(this_tcphdr, &tmp_ts) && 
  	before(tmp_ts, snd->curr_ts))
  return; 	
  
  if ((this_tcphdr->th_flags & TH_ACK)) {
    if (from_client && a_tcp->client.state == TCP_SYN_SENT &&
	a_tcp->server.state == TCP_SYN_RECV) {
      if (ntohl(this_tcphdr->th_ack) == a_tcp->server.seq) {
	a_tcp->client.state = TCP_ESTABLISHED;
	a_tcp->client.ack_seq = ntohl(this_tcphdr->th_ack);
	{
	  struct proc_node *i;
	  struct lurker_node *j;
	  void *data;
	  
	  a_tcp->server.state = TCP_ESTABLISHED;
	  a_tcp->nids_state = NIDS_JUST_EST;
	  for (i = tcp_procs; i; i = i->next) {
	    char whatto = 0;
	    char cc = a_tcp->client.collect;
	    char sc = a_tcp->server.collect;
	    char ccu = a_tcp->client.collect_urg;
	    char scu = a_tcp->server.collect_urg;
	    
	    (i->item) (a_tcp, &data);
	    if (cc < a_tcp->client.collect)
	      whatto |= COLLECT_cc;
	    if (ccu < a_tcp->client.collect_urg)
	      whatto |= COLLECT_ccu;
	    if (sc < a_tcp->server.collect)
	      whatto |= COLLECT_sc;
	    if (scu < a_tcp->server.collect_urg)
	      whatto |= COLLECT_scu;
	    if (nids_params.one_loop_less) {
	    		if (a_tcp->client.collect >=2) {
	    			a_tcp->client.collect=cc;
	    			whatto&=~COLLECT_cc;
	    		}
	    		if (a_tcp->server.collect >=2 ) {
	    			a_tcp->server.collect=sc;
	    			whatto&=~COLLECT_sc;
	    		}
	    }  
	    if (whatto) {
	      j = mknew(struct lurker_node);
	      j->item = i->item;
	      j->data = data;
	      j->whatto = whatto;
	      j->next = a_tcp->listeners;
	      a_tcp->listeners = j;
	    }
	  }
	  if (!a_tcp->listeners) {
	    free_tcp(a_tcp);
	    return;
	  }
	  a_tcp->nids_state = NIDS_DATA;
	}
      }
      // return;
    }
  }
Пример #27
0
void
add_from_skb(struct tcp_stream * a_tcp, struct half_stream * rcv,
	     struct half_stream * snd,
	     u_char *data, u_int datalen,
	     u_int this_seq, char fin, char urg, u_int urg_ptr)
{
  u_int lost = abs(EXP_SEQ + a_tcp->totallost - this_seq);
  int mylost =  this_seq - EXP_SEQ -a_tcp->totallost;

  if(mylost > 0){
    a_tcp->totallost += mylost;
    lost = 0;
  }  
/*
  else if(mylost < 0){
    if(datalen <= lost)
        return;
 
  }
*/
  lost = 0;
  

  if(before_seq == this_seq){
     return;
  }
     
  before_seq = this_seq;
  before_len = datalen;

  int to_copy, to_copy2;
  
  if (urg && after(urg_ptr, EXP_SEQ - 1) &&
      (!rcv->urg_seen || after(urg_ptr, rcv->urg_ptr))) {
    rcv->urg_ptr = urg_ptr;
    rcv->urg_seen = 1;
  }
  if (after(rcv->urg_ptr + 1, this_seq + lost) && //if 2
      before(rcv->urg_ptr, this_seq + datalen)) {
    to_copy = rcv->urg_ptr - (this_seq + lost);
    if (to_copy > 0) {  //if 1
      if (rcv->collect) {
	add2buf(rcv, data + lost, to_copy);
	notify(a_tcp, rcv);
      }
      else {
	rcv->count += to_copy;
	rcv->offset = rcv->count; // clear the buffer 
      }
    }//if 1
    rcv->urgdata = data[rcv->urg_ptr - this_seq];
    rcv->count_new_urg = 1;
    notify(a_tcp, rcv);
    rcv->count_new_urg = 0;
    rcv->urg_count++;
    to_copy2 = this_seq + datalen - rcv->urg_ptr - 1;
    if (to_copy2 > 0) {// if 4
      if (rcv->collect) {
	add2buf(rcv, data + lost + to_copy + 1, to_copy2);
	notify(a_tcp, rcv);
      }
      else {
	rcv->count += to_copy2;
	rcv->offset = rcv->count; // clear the buffer 
      }
    }// if 4
  }// if 2
  else {
    if (datalen -lost > 0) {
      if (rcv->collect) {
	add2buf(rcv, data + lost, datalen - lost);
	notify(a_tcp, rcv);
      }
      else {
	rcv->count += datalen - lost;
	rcv->offset = rcv->count; // clear the buffer 
      }
    }
  }//else 2
  if (fin)
    snd->state = FIN_SENT;
}
Пример #28
0
static bool tcp_in_window(const struct nf_conn *ct,
			  struct ip_ct_tcp *state,
			  enum ip_conntrack_dir dir,
			  unsigned int index,
			  const struct sk_buff *skb,
			  unsigned int dataoff,
			  const struct tcphdr *tcph,
			  u_int8_t pf)
{
	struct net *net = nf_ct_net(ct);
	struct ip_ct_tcp_state *sender = &state->seen[dir];
	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
	const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
	__u32 seq, ack, sack, end, win, swin;
	s16 receiver_offset;
	bool res;

	/*
	 * Get the required data from the packet.
	 */
	seq = ntohl(tcph->seq);
	ack = sack = ntohl(tcph->ack_seq);
	win = ntohs(tcph->window);
	end = segment_seq_plus_len(seq, skb->len, dataoff, tcph);

	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
		tcp_sack(skb, dataoff, tcph, &sack);

	/* Take into account NAT sequence number mangling */
	receiver_offset = NAT_OFFSET(pf, ct, !dir, ack - 1);
	ack -= receiver_offset;
	sack -= receiver_offset;

	pr_debug("tcp_in_window: START\n");
	pr_debug("tcp_in_window: ");
	nf_ct_dump_tuple(tuple);
	pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
		 seq, ack, receiver_offset, sack, receiver_offset, win, end);
	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
		 sender->td_end, sender->td_maxend, sender->td_maxwin,
		 sender->td_scale,
		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
		 receiver->td_scale);

	if (sender->td_maxwin == 0) {
		/*
		 * Initialize sender data.
		 */
		if (tcph->syn) {
			/*
			 * SYN-ACK in reply to a SYN
			 * or SYN from reply direction in simultaneous open.
			 */
			sender->td_end =
			sender->td_maxend = end;
			sender->td_maxwin = (win == 0 ? 1 : win);

			tcp_options(skb, dataoff, tcph, sender);
			/*
			 * RFC 1323:
			 * Both sides must send the Window Scale option
			 * to enable window scaling in either direction.
			 */
			if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
			      && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
				sender->td_scale =
				receiver->td_scale = 0;
			if (!tcph->ack)
				/* Simultaneous open */
				return true;
		} else {
			/*
			 * We are in the middle of a connection,
			 * its history is lost for us.
			 * Let's try to use the data from the packet.
			 */
			sender->td_end = end;
			sender->td_maxwin = (win == 0 ? 1 : win);
			sender->td_maxend = end + sender->td_maxwin;
		}
	} else if (((state->state == TCP_CONNTRACK_SYN_SENT
		     && dir == IP_CT_DIR_ORIGINAL)
		   || (state->state == TCP_CONNTRACK_SYN_RECV
		     && dir == IP_CT_DIR_REPLY))
		   && after(end, sender->td_end)) {
		/*
		 * RFC 793: "if a TCP is reinitialized ... then it need
		 * not wait at all; it must only be sure to use sequence
		 * numbers larger than those recently used."
		 */
		sender->td_end =
		sender->td_maxend = end;
		sender->td_maxwin = (win == 0 ? 1 : win);

		tcp_options(skb, dataoff, tcph, sender);
	}

	if (!(tcph->ack)) {
		/*
		 * If there is no ACK, just pretend it was set and OK.
		 */
		ack = sack = receiver->td_end;
	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) ==
		    (TCP_FLAG_ACK|TCP_FLAG_RST))
		   && (ack == 0)) {
		/*
		 * Broken TCP stacks, that set ACK in RST packets as well
		 * with zero ack value.
		 */
		ack = sack = receiver->td_end;
	}

	if (seq == end
	    && (!tcph->rst
		|| (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
		/*
		 * Packets contains no data: we assume it is valid
		 * and check the ack value only.
		 * However RST segments are always validated by their
		 * SEQ number, except when seq == 0 (reset sent answering
		 * SYN.
		 */
		seq = end = sender->td_end;

	pr_debug("tcp_in_window: ");
	nf_ct_dump_tuple(tuple);
	pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
		 seq, ack, receiver_offset, sack, receiver_offset, win, end);
	pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
		 "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
		 sender->td_end, sender->td_maxend, sender->td_maxwin,
		 sender->td_scale,
		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
		 receiver->td_scale);

	pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
		 before(seq, sender->td_maxend + 1),
		 after(end, sender->td_end - receiver->td_maxwin - 1),
		 before(sack, receiver->td_end + 1),
		 after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1));

	if (before(seq, sender->td_maxend + 1) &&
	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
	    before(sack, receiver->td_end + 1) &&
	    after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) {
		/*
		 * Take into account window scaling (RFC 1323).
		 */
		if (!tcph->syn)
			win <<= sender->td_scale;

		/*
		 * Update sender data.
		 */
		swin = win + (sack - ack);
		if (sender->td_maxwin < swin)
			sender->td_maxwin = swin;
		if (after(end, sender->td_end)) {
			sender->td_end = end;
			sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
		}
		if (tcph->ack) {
			if (!(sender->flags & IP_CT_TCP_FLAG_MAXACK_SET)) {
				sender->td_maxack = ack;
				sender->flags |= IP_CT_TCP_FLAG_MAXACK_SET;
			} else if (after(ack, sender->td_maxack))
				sender->td_maxack = ack;
		}

		/*
		 * Update receiver data.
		 */
		if (after(end, sender->td_maxend))
			receiver->td_maxwin += end - sender->td_maxend;
		if (after(sack + win, receiver->td_maxend - 1)) {
			receiver->td_maxend = sack + win;
			if (win == 0)
				receiver->td_maxend++;
		}
		if (ack == receiver->td_end)
			receiver->flags &= ~IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;

		/*
		 * Check retransmissions.
		 */
		if (index == TCP_ACK_SET) {
			if (state->last_dir == dir
			    && state->last_seq == seq
			    && state->last_ack == ack
			    && state->last_end == end
			    && state->last_win == win)
				state->retrans++;
			else {
				state->last_dir = dir;
				state->last_seq = seq;
				state->last_ack = ack;
				state->last_end = end;
				state->last_win = win;
				state->retrans = 0;
			}
		}
		res = true;
	} else {
		res = false;
		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
		    nf_ct_tcp_be_liberal)
			res = true;
		if (!res && LOG_INVALID(net, IPPROTO_TCP))
			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
			"nf_ct_tcp: %s ",
			before(seq, sender->td_maxend + 1) ?
			after(end, sender->td_end - receiver->td_maxwin - 1) ?
			before(sack, receiver->td_end + 1) ?
			after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG"
			: "ACK is under the lower bound (possible overly delayed ACK)"
			: "ACK is over the upper bound (ACKed data not seen yet)"
			: "SEQ is under the lower bound (already ACKed data retransmitted)"
			: "SEQ is over the upper bound (over the window of the receiver)");
	}

	pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
		 "receiver end=%u maxend=%u maxwin=%u\n",
		 res, sender->td_end, sender->td_maxend, sender->td_maxwin,
		 receiver->td_end, receiver->td_maxend, receiver->td_maxwin);

	return res;
}
Пример #29
0
/* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct nf_conn *ct,
		      const struct sk_buff *skb,
		      unsigned int dataoff,
		      enum ip_conntrack_info ctinfo,
		      u_int8_t pf,
		      unsigned int hooknum)
{
	struct net *net = nf_ct_net(ct);
	struct nf_conntrack_tuple *tuple;
#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
	struct nf_conntrack_tuple *tupleInverseDir;
#endif
	enum tcp_conntrack new_state, old_state;
	enum ip_conntrack_dir dir;
	const struct tcphdr *th;
	struct tcphdr _tcph;
	unsigned long timeout;
	unsigned int index;

	th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
	BUG_ON(th == NULL);

	spin_lock_bh(&ct->lock);
	old_state = ct->proto.tcp.state;
	dir = CTINFO2DIR(ctinfo);
	index = get_conntrack_index(th);
	new_state = tcp_conntracks[dir][index][old_state];
	tuple = &ct->tuplehash[dir].tuple;
#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
	tupleInverseDir	= &ct->tuplehash[!dir].tuple;
#endif
	switch (new_state) {
	case TCP_CONNTRACK_SYN_SENT:
		if (old_state < TCP_CONNTRACK_TIME_WAIT)
			break;
		/* RFC 1122: "When a connection is closed actively,
		 * it MUST linger in TIME-WAIT state for a time 2xMSL
		 * (Maximum Segment Lifetime). However, it MAY accept
		 * a new SYN from the remote TCP to reopen the connection
		 * directly from TIME-WAIT state, if..."
		 * We ignore the conditions because we are in the
		 * TIME-WAIT state anyway.
		 *
		 * Handle aborted connections: we and the server
		 * think there is an existing connection but the client
		 * aborts it and starts a new one.
		 */
		if (((ct->proto.tcp.seen[dir].flags
		      | ct->proto.tcp.seen[!dir].flags)
		     & IP_CT_TCP_FLAG_CLOSE_INIT)
		    || (ct->proto.tcp.last_dir == dir
		        && ct->proto.tcp.last_index == TCP_RST_SET)) {
			/* Attempt to reopen a closed/aborted connection.
			 * Delete this connection and look up again. */
			spin_unlock_bh(&ct->lock);

			/* Only repeat if we can actually remove the timer.
			 * Destruction may already be in progress in process
			 * context and we must give it a chance to terminate.
			 */
			if (nf_ct_kill(ct))
				return -NF_REPEAT;
			return NF_DROP;
		}
		/* Fall through */
	case TCP_CONNTRACK_IGNORE:
		/* Ignored packets:
		 *
		 * Our connection entry may be out of sync, so ignore
		 * packets which may signal the real connection between
		 * the client and the server.
		 *
		 * a) SYN in ORIGINAL
		 * b) SYN/ACK in REPLY
		 * c) ACK in reply direction after initial SYN in original.
		 *
		 * If the ignored packet is invalid, the receiver will send
		 * a RST we'll catch below.
		 */
		if (index == TCP_SYNACK_SET
		    && ct->proto.tcp.last_index == TCP_SYN_SET
		    && ct->proto.tcp.last_dir != dir
		    && ntohl(th->ack_seq) == ct->proto.tcp.last_end) {
			/* b) This SYN/ACK acknowledges a SYN that we earlier
			 * ignored as invalid. This means that the client and
			 * the server are both in sync, while the firewall is
			 * not. We kill this session and block the SYN/ACK so
			 * that the client cannot but retransmit its SYN and
			 * thus initiate a clean new session.
			 */
			spin_unlock_bh(&ct->lock);
			if (LOG_INVALID(net, IPPROTO_TCP))
				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
					  "nf_ct_tcp: killing out of sync session ");
			nf_ct_kill(ct);
			return NF_DROP;
		}
		ct->proto.tcp.last_index = index;
		ct->proto.tcp.last_dir = dir;
		ct->proto.tcp.last_seq = ntohl(th->seq);
		ct->proto.tcp.last_end =
		    segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th);

		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_TCP))
			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
				  "nf_ct_tcp: invalid packet ignored ");
		return NF_ACCEPT;
	case TCP_CONNTRACK_MAX:
		/* Invalid packet */
		pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
			 dir, get_conntrack_index(th), old_state);
		spin_unlock_bh(&ct->lock);
		if (LOG_INVALID(net, IPPROTO_TCP))
			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
				  "nf_ct_tcp: invalid state ");
		return -NF_ACCEPT;
	case TCP_CONNTRACK_CLOSE:
		if (index == TCP_RST_SET
		    && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET)
		    && before(ntohl(th->seq), ct->proto.tcp.seen[!dir].td_maxack)) {
			/* Invalid RST  */
			spin_unlock_bh(&ct->lock);
			if (LOG_INVALID(net, IPPROTO_TCP))
				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
					  "nf_ct_tcp: invalid RST ");
			return -NF_ACCEPT;
		}
		if (index == TCP_RST_SET
		    && ((test_bit(IPS_SEEN_REPLY_BIT, &ct->status)
			 && ct->proto.tcp.last_index == TCP_SYN_SET)
			|| (!test_bit(IPS_ASSURED_BIT, &ct->status)
			    && ct->proto.tcp.last_index == TCP_ACK_SET))
		    && ntohl(th->ack_seq) == ct->proto.tcp.last_end) {
			/* RST sent to invalid SYN or ACK we had let through
			 * at a) and c) above:
			 *
			 * a) SYN was in window then
			 * c) we hold a half-open connection.
			 *
			 * Delete our connection entry.
			 * We skip window checking, because packet might ACK
			 * segments we ignored. */
			goto in_window;
		}
		/* Just fall through */
	default:
		/* Keep compilers happy. */
		break;
	}

#if defined(CONFIG_MV_ETH_NFP_CT_LEARN)
	/*
	 * When connection is handled by NFP, we have to relax TCP tracking
	 * rules as not all packets goes through Linux conntrack.
	 */
	if ((tuple->nfp) || (tupleInverseDir->nfp))
		goto in_window;
#endif /* CONFIG_MV_ETH_NFP_CT_LEARN */

	if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
			   skb, dataoff, th, pf)) {
		spin_unlock_bh(&ct->lock);
		return -NF_ACCEPT;
	}
     in_window:
	/* From now on we have got in-window packets */
	ct->proto.tcp.last_index = index;
	ct->proto.tcp.last_dir = dir;

	pr_debug("tcp_conntracks: ");
	nf_ct_dump_tuple(tuple);
	pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
		 (th->syn ? 1 : 0), (th->ack ? 1 : 0),
		 (th->fin ? 1 : 0), (th->rst ? 1 : 0),
		 old_state, new_state);

	ct->proto.tcp.state = new_state;
	if (old_state != new_state
	    && new_state == TCP_CONNTRACK_FIN_WAIT)
		ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;

	if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans &&
	    tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans)
		timeout = nf_ct_tcp_timeout_max_retrans;
	else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
		 IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
		 tcp_timeouts[new_state] > nf_ct_tcp_timeout_unacknowledged)
		timeout = nf_ct_tcp_timeout_unacknowledged;
	else
		timeout = tcp_timeouts[new_state];
	spin_unlock_bh(&ct->lock);

	if (new_state != old_state)
		nf_conntrack_event_cache(IPCT_PROTOINFO, ct);

	if (!test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
		/* If only reply is a RST, we can consider ourselves not to
		   have an established connection: this is a fairly common
		   problem case, so we can delete the conntrack
		   immediately.  --RR */
		if (th->rst) {
			nf_ct_kill_acct(ct, ctinfo, skb);
			return NF_ACCEPT;
		}
	} else if (!test_bit(IPS_ASSURED_BIT, &ct->status)
		   && (old_state == TCP_CONNTRACK_SYN_RECV
		       || old_state == TCP_CONNTRACK_ESTABLISHED)
		   && new_state == TCP_CONNTRACK_ESTABLISHED) {
		/* Set ASSURED if we see see valid ack in ESTABLISHED
		   after SYN_RECV or a valid answer for a picked up
		   connection. */
		set_bit(IPS_ASSURED_BIT, &ct->status);
		nf_conntrack_event_cache(IPCT_STATUS, ct);
	}
	nf_ct_refresh_acct(ct, ctinfo, skb, timeout);

	return NF_ACCEPT;
}
static int tcp_in_window(struct ip_ct_tcp *state,
			 enum ip_conntrack_dir dir,
			 unsigned int index,
			 const struct sk_buff *skb,
			 unsigned int dataoff,
			 struct tcphdr *tcph,
			 int pf)
{
	struct ip_ct_tcp_state *sender = &state->seen[dir];
	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
	__u32 seq, ack, sack, end, win;
#if defined (CONFIG_RA_NAT_NONE)
	__u32 swin;
#endif
	int res;

	/*
	 * Get the required data from the packet.
	 */
	seq = ntohl(tcph->seq);
	ack = sack = ntohl(tcph->ack_seq);
	win = ntohs(tcph->window);
	end = segment_seq_plus_len(seq, skb->len, dataoff, tcph);

	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
		tcp_sack(skb, dataoff, tcph, &sack);

	DEBUGP("tcp_in_window: START\n");
	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
		NIPQUAD(iph->saddr), ntohs(tcph->source),
		NIPQUAD(iph->daddr), ntohs(tcph->dest),
		seq, ack, sack, win, end);
	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
		sender->td_end, sender->td_maxend, sender->td_maxwin,
		sender->td_scale,
		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
		receiver->td_scale);

	if (sender->td_end == 0) {
		/*
		 * Initialize sender data.
		 */
		if (tcph->syn && tcph->ack) {
			/*
			 * Outgoing SYN-ACK in reply to a SYN.
			 */
			sender->td_end =
			sender->td_maxend = end;
			sender->td_maxwin = (win == 0 ? 1 : win);

			tcp_options(skb, dataoff, tcph, sender);
			/*
			 * RFC 1323:
			 * Both sides must send the Window Scale option
			 * to enable window scaling in either direction.
			 */
			if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
			      && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
				sender->td_scale =
				receiver->td_scale = 0;
		} else {
			/*
			 * We are in the middle of a connection,
			 * its history is lost for us.
			 * Let's try to use the data from the packet.
			 */
			sender->td_end = end;
			sender->td_maxwin = (win == 0 ? 1 : win);
			sender->td_maxend = end + sender->td_maxwin;
		}
	} else if (((state->state == TCP_CONNTRACK_SYN_SENT
		     && dir == IP_CT_DIR_ORIGINAL)
		   || (state->state == TCP_CONNTRACK_SYN_RECV
		     && dir == IP_CT_DIR_REPLY))
		   && after(end, sender->td_end)) {
		/*
		 * RFC 793: "if a TCP is reinitialized ... then it need
		 * not wait at all; it must only be sure to use sequence
		 * numbers larger than those recently used."
		 */
		sender->td_end =
		sender->td_maxend = end;
		sender->td_maxwin = (win == 0 ? 1 : win);

		tcp_options(skb, dataoff, tcph, sender);
	}

	if (!(tcph->ack)) {
		/*
		 * If there is no ACK, just pretend it was set and OK.
		 */
		ack = sack = receiver->td_end;
	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) ==
		    (TCP_FLAG_ACK|TCP_FLAG_RST))
		   && (ack == 0)) {
		/*
		 * Broken TCP stacks, that set ACK in RST packets as well
		 * with zero ack value.
		 */
		ack = sack = receiver->td_end;
	}

	if (seq == end
	    && (!tcph->rst
		|| (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
		/*
		 * Packets contains no data: we assume it is valid
		 * and check the ack value only.
		 * However RST segments are always validated by their
		 * SEQ number, except when seq == 0 (reset sent answering
		 * SYN.
		 */
		seq = end = sender->td_end;

	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
	       "seq=%u ack=%u sack =%u win=%u end=%u\n",
		NIPQUAD(iph->saddr), ntohs(tcph->source),
		NIPQUAD(iph->daddr), ntohs(tcph->dest),
		seq, ack, sack, win, end);
	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
		sender->td_end, sender->td_maxend, sender->td_maxwin,
		sender->td_scale,
		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
		receiver->td_scale);

	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
		before(seq, sender->td_maxend + 1),
		after(end, sender->td_end - receiver->td_maxwin - 1),
		before(sack, receiver->td_end + 1),
		after(ack, receiver->td_end - MAXACKWINDOW(sender)));

#if defined (CONFIG_RA_NAT_NONE)
	if (before(seq, sender->td_maxend + 1) &&
	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
	    before(sack, receiver->td_end + 1) &&
	    after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
		/*
		 * Take into account window scaling (RFC 1323).
		 */
		if (!tcph->syn)
			win <<= sender->td_scale;

		/*
		 * Update sender data.
		 */
		swin = win + (sack - ack);
		if (sender->td_maxwin < swin)
			sender->td_maxwin = swin;
		if (after(end, sender->td_end))
			sender->td_end = end;
		/*
		 * Update receiver data.
		 */
		if (after(end, sender->td_maxend))
			receiver->td_maxwin += end - sender->td_maxend;
		if (after(sack + win, receiver->td_maxend - 1)) {
			receiver->td_maxend = sack + win;
			if (win == 0)
				receiver->td_maxend++;
		}

		/*
		 * Check retransmissions.
		 */
		if (index == TCP_ACK_SET) {
			if (state->last_dir == dir
			    && state->last_seq == seq
			    && state->last_ack == ack
			    && state->last_end == end
			    && state->last_win == win)
				state->retrans++;
			else {
				state->last_dir = dir;
				state->last_seq = seq;
				state->last_ack = ack;
				state->last_end = end;
				state->last_win = win;
				state->retrans = 0;
			}
		}
		res = 1;
	} else {
		res = 0;
		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
		    nf_ct_tcp_be_liberal)
			res = 1;
		if (!res && LOG_INVALID(IPPROTO_TCP))
			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
			"nf_ct_tcp: %s ",
			before(seq, sender->td_maxend + 1) ?
			after(end, sender->td_end - receiver->td_maxwin - 1) ?
			before(sack, receiver->td_end + 1) ?
			after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
			: "ACK is under the lower bound (possible overly delayed ACK)"
			: "ACK is over the upper bound (ACKed data not seen yet)"
			: "SEQ is under the lower bound (already ACKed data retransmitted)"
			: "SEQ is over the upper bound (over the window of the receiver)");
	}
#else
	res = 1;
#endif

	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
	       "receiver end=%u maxend=%u maxwin=%u\n",
		res, sender->td_end, sender->td_maxend, sender->td_maxwin,
		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);

	return res;
}