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; }
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); } } }
/** * 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; }
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); }
/* 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); }
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); } }
/* 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); }
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(); }
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(); }
// 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); } }
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; }
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); } } } }
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(); }
/* 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; }
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; }
/* * 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; }
// ------------------------- 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; }
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"; } } }
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; }
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; }
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; }
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; } }
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; }
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; }
/* 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; }